傳送門
對於這個題目很明顯的就是狀壓dp,不過,作為乙個不會狀壓dp的蒟蒻,考場讓只能根據大佬們的之前聊天和對狀壓dp的印象來瞎搞
狀態是這樣設計的:
f[i,j] 表示轉移到從第i個位置出發的j表示五個的動物的狀態能使多少個小朋友滿意 s[i,j]所以,狀態量其實和小朋友的人數沒什麼關係,總狀態量是n*25 =320 000,兩個陣列是640 000,16m的空間是夠用的。表示從i出發的5個位置中表示j的狀態使多少個小朋友滿意
對於每個小朋友,讀入的時候就表示出來兩個01串,這裡用x和y表示,然後列舉狀態,分別和x和y作比較,如果可以,那麼s[e][狀態]就++。
比較是這樣的:
for
(int i=
0; i++i)
預處理結束了,就要開始dp了,同樣也是要列舉初始狀態,把初始狀態作為0,其他為-inf,進行轉移。
轉移的過程中:
for
(re int i=
1; i<=n;
++i)
for(re int k=
0; k++k)
f[i]
[k]=
max(f[i-1]
[(k<<1)
%lim]
,f[i-1]
[((k<<1)
+1)%lim]
)+s[i]
[k];
//從上個狀態的最大值轉移過來後加上此狀態這個位置的小朋友滿意個數
/* ((k<<1)+1)%lim abcde -> bcde1
(k<<1)%lim abcde -> bcde0
*/
最後因為饒了一圈,所以回到了最初列舉的狀態。
完整**如下:
#include
#include
#include
#include
#include
using
namespace std;
#define re register
#define gc getchar()
#define ll long long
#define il inline
const
int n=
10010
,lim=(1
<<5)
,inf=
1e9+7;
il int
read()
while
(ch>=
'0'&&ch<=
'9')
return x*f;
}int n,c,f[n]
[lim]
,s[n]
[lim]
,ans;
intmain()
for(
int i=
1; i<=l;
++i)
for(
int i=
0; i++i)
}for
(re int j=
0; j++j)
cout
}
於是,小蒟蒻的第一次狀壓dp get 題解 APIO2007動物園
首先一眼感受到這題特別的性質 5個?這麼小的,感覺就像是狀壓。腦補了一下,如果沒有環的話應該很好做吧 有環怎麼辦?5真的很小的,隨便亂搞肯定也可以。那就放在外面暴力列舉吧。然後正解就出來了。然而這題題面真的有毒吧。說好的不能全部選走?我還多加了乙個維度,結果資料裡面允許全部取走 然後對於 5的點單獨...
APIO2007 動物園 題解
x 原題鏈結 有一圈圍欄,每個圍欄有一種動物,有若干個小朋友,每個小朋友能看到連續的 5 個動物,每個小朋友對每種的動物的喜好不一樣,如果乙個小朋友會高興,當且僅當至少有乙個他害怕的動物被移走,或者是至少有乙個他喜歡的動物沒有被移走。問調整某些動物後,最多有多少個小朋友會高興。題目的目的是移走若干動...
APIO2007 動物園 狀壓DP
表示調這題調到失智了,調了好久發現是因為dp的方向反了。首先我們觀察到雖然動物和小朋友數量都很多,但是每個小朋友可以看到的動物只有連續的5個!因此我們考慮狀壓,2 5還是可以承受的。再觀察到因為是連續的5個,所以對於任意一段以i為開頭的區間而言,區間都是已經被固定了的。因此對於每個區間單獨考慮。f ...