P2157 SDOI2009 學校食堂 狀壓DP

2021-10-25 00:26:53 字數 1536 閱讀 7580

有點複雜,自行瀏覽吧 題目鏈結

我們發現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 ...