1. 程式人生 > >【BZOJ1226】【SDOI2009】學校食堂

【BZOJ1226】【SDOI2009】學校食堂

題目點這裡

由題目可知,假如第i個人還沒有取,則絕不可能取i+7之後的人,因為第i個人的最大容忍度不會超過7;如果第i個人之前全部取完了,則目前為止最後一個選的不可能是i-8之前的人,因為i-1不可能先於i-9及之前的人被選。故,可以設計狀態f [i, S, k]表示到第i個人為止,他之前的人都取過了,他及他後面7個人的還沒取過的集合是S,前一個取的人是k的最優代價。因此可以動態規劃求解。

每次列舉一個狀態f [i, S, k],如果S中沒有第i個人了,就將f [i, S, k]轉移給f [i+1, S’, k],這裡S’多了第i+8個人。如果S中有第i個人,則列舉S中的一個符合要求的人j作為k之後所取的那個人,即將狀態f [i, S, k]轉移給f [i, S-{j}, j]。

記錄一個集合,我們可以採用二進位制壓位得到的整數S表示,若S and 1≠0,則說明第i個人在集合中是存在的,若S and 2≠0,說明第i+1個人在集合中是存在的,依此類推。

而根據第一段的分析,狀態的第三維的值不需要從1到N,只需要記錄一個對i的相對位置就行,數值從-8到7。

現在,就可以用狀態f [i, S, k]表示到第i個人為止,他之前的人都取過了,他及他後面7個人的狀態是S,前一個取的人是i+k的最優代價。對於上述兩種轉移,如果S表示的集合中沒有第i個人了,便是將f [i, S, k]轉移給f [i+1, +27, k-1];如果S表示的集合中有第i個人,則列舉其中一個符合要求的人j作為i+k之後所取的那個人,將狀態轉移給f [i, S-2j-i, j-i]。根據轉移可以知道列舉時第一維必須從小到大列舉,第二維必須從大到小列舉。