有點複雜,自行瀏覽吧 題目鏈結
我們發現dp轉移時需要記錄以下幾個資訊:
打飯佇列的隊首是誰,上乙個打飯的是誰,佇列前b[i
]b[i]
b[i]
個人的狀態
然後我們根據這些資訊設立dp狀態,記f[i
][j]
[k
]f[i][j][k]
f[i][j
][k]
表示該第i
ii個人打飯(等價於前i−1
i-1i−
1個人已經買完飯)此時佇列前7個人的狀態是j
jj,上乙個打飯的人是i+k
i+ki+
k。由於打飯的人在i
ii的前後都可以,所以k
kk的範圍就是[−8
,8
][-8,8]
[−8,8]
,加上偏移量就是[0,
16]
[0,16]
[0,16]
接下來我們考慮轉移,分為兩種情況:
第i
ii個人已經買完飯了,也就是說直接將狀態轉移到i+1
i+1i+
1就可以了
f[i+1]
[j>>1]
[k-1]=
min(f[i+1]
[j>>1]
[k-1
],f[i]
[j][k]
);
第i
ii個人還沒有買飯,那就在所有人都能忍受的範圍內列舉買飯的人是誰
f[i]
[j|(
1<][l]
=min
(f[i]
[j|(
1<][l]
,f[i]
[j][k]
+(t[i+k]
^t[i+l]))
;
狀態初始化為f[1
][0]
[7
]f[1][0][7]
f[1][0
][7]
表示該第1
11個人買飯,此時身後所有人都沒有買完,上乙個買的人是第7−8
7-87−
8個,最後統計列舉i
ii然後取f[n
+1][
0][i
]f[n+1][0][i]
f[n+1]
[0][
i]的最小值
#include
using
namespace std;
namespace zzc}}
}}}}
int ans=
0x3f3f3f
;for
(int i=
0;i<=
8;i++
) ans=
min(ans,f[n+1]
[0][i]);
printf
("%d\n"
,ans);}
}}intmain()
P2157 SDOI2009 學校食堂
傳送門 做菜主要是按時間順序,所以可以考慮dp 但是可能後面的人會先打飯 可以發現同學最多只能讓後面的第7個同學先打飯 可以從這裡入手考慮問題 把每8個一起的同學看成乙個狀態 在他們之前的人都已經打好飯了 想象乙個從左往右的佇列 從1 i 1 的同學都打完飯了 然後需要知道的狀態是 i i 7 共8...
P2157 SDOI2009 學校食堂
小f 的學校在城市的乙個偏僻角落,所有學生都只好在學校吃飯。學校有乙個食堂,雖然簡陋,但食堂大廚總能做出讓同學們滿意的菜餚。當然,不同的人口味也不一定相同,但每個人的口味都可以用乙個非負整數表示。由於人手不夠,食堂每次只能為乙個人做菜。做每道菜所需的時間是和前一道菜有關的,若前一道菜的對應的口味是a...
Luogu2157 SDOI2009 學校食堂
link 給定 n 個學生的口味和忍耐度,若前一道菜的對應的口味是a,這一道為b,則做這道菜所需的時間為 a b a b 而做第一道菜是不需要計算時間的.每個學生可以忍耐忍耐度以下的人在他前面插隊買飯 求最小的做飯時間 n le 1000,b i le 8 令 f 表示第 i 個人前面的狀態是 s ...