[BZOJ1032][P1840] 祖瑪 記憶化搜索 動態規劃
阿新 • • 發佈:2017-11-04
不用 小遊戲 之間 ++ ios 多少 hide 大於 mat
http://www.cnblogs.com/AndreMouche/archive/2011/02/27/1966504.html
↑大神的程序...
狀態可以通過記憶化搜索找(復習時間:記憶化搜索就是把找到的東西都存在f[i][j][cnt]裏下次用這個值就不用搜了... )
f[i][j][cnt] =x 表示從i到j的珠子前有cnt個連續的緊跟在i前面的與第i個珠子相同的珠子,此時需要x個珠子可以讓他們全部消失(BOOM!)
搜索時也是這三個變量(雖然記錄的是cnt,但是cnt+1才是此時記錄的連續的珠子的個數(加上i位置的珠子))
下面是手把手的貼心的和貼代碼沒兩樣的題解...聰明人就不要往下看了...(我找不到要點所以就把代碼含義敘述了一遍)
當f[i][j][cnt] 儲存有有意義的值(搜索過了)的時候,直接返回該值;
i=j時 返回k(k個珠子時可以可以消失)-(1+cnt)(把最後剩下來的珠子補成k個)
i>j時,當然不需要珠子啦...返回0
連續的珠子數(cnt+1)大於等於k時,則消去這些珠子,搜索從i+1到j個珠子(因為前面多於k的珠子自動消去所以此時f[i+1][j][0]和f[i][j][cnt]等效.....)
小於時,則搜索手動加進去一個珠子的狀態,即f[i][j][cnt+1]+1和f[i][j][cnt]等效...
此時該搜的都搜了,,就需要dp來找狀態的最優值...,在i和j之間找一個w,w位置的小球和i位置的一樣......則
f[i][j][cnt] =min(f[i][j][cnt],f[i+1][w-1][0]+f[w][j][min(cnt+1,k-1)]);
這個應該很好理解所以我就不手把手解釋了....就是消去中間的珠子然後讓兩邊一樣的珠子撞在一起再消一次,正常的祖瑪方法......
最後把f[i][j][cnt]的值返回
有些地方我沒寫dfs(i,j,cnt)什麽的但是不代表不用遞歸.....某個f[i][j][cnt]如果沒值當然要搜索它啊...仙女教母不會自動給你初始化成正確答案的,這是搜索,醒醒!!!!而且搜索之後別忘了記憶化...所以這個鬼畜的東西才叫記憶化搜索...
歡迎神犇捉蟲...雖然神犇看這麽簡單的題估計題解都不願意寫...
因為校對無能所以真的有什麽錯誤我不負責任...
代碼
描述 Description | |||
某天,小x在玩一個經典小遊戲——zumo。 zumo遊戲的規則是,給你一段長度為n的連續的彩色珠子,珠子的顏色不一定完全相同,但是,如果連續相同顏色的珠子大於等於k個,這些珠子就會消失。當然,最初的狀態可能不必要直接消掉一些珠子(見樣例)。現在你有無窮個所有顏色的珠子,並且你可以在任意地方插入珠子。 現在提出問題:給你一個固定的狀態,你最少需要用多少個小球,才能將所有的小球消去。 |
|||
輸入格式 Input Format | |||
第一行是兩個整數,n (1 ≤ n ≤ 100)和k(2 ≤ k ≤5),表示有n個彩色珠子,必須連續有k個以上(包括k個)相同顏色的珠子,這些珠子才會消失。 接下來一行包含n個用空格隔開的整數,每個數在1到100之間,每個數值表示一個珠子的顏色,相同的數字意味著珠子的顏色相同。 | |||
輸出格式 Output Format | |||
一個整數,表示最少需要用多少個小球,才能讓所有的小球消失。 |
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 int n,k; 9 int a[110][2]={}; 10 int dd[110]={}; 11 int f[110][110][110]; 12 int fff(int b1,int b,int cnt){ 13 int &cur=f[b1][b][cnt]; 14 if(cur!=-1) return cur; 15 if(b1==b){ 16 cur=k-cnt-1; 17 return cur; 18 } 19 if(b1>b){ 20 cur=0; 21 return cur; 22 } 23 if(cnt<k-1){ 24 cur=fff(b1,b,cnt+1)+1; 25 } 26 else{ 27 if(cnt>=k-1){ 28 cur=fff(b1+1,b,0); 29 } 30 } 31 int i; 32 for(int i=b1+1;i<=b;i++){ 33 if(dd[i]!=dd[b1]) continue; 34 int value=fff(b1+1,i-1,0)+fff(i,b,min(cnt+1,k-1)); 35 if(value<cur) cur=value; 36 } 37 return cur; 38 } 39 int main(){ 40 cin>>n>>k; 41 int tail=-1; 42 int sumn=0; 43 for(int i=1;i<=n;i++){ 44 cin>>dd[i]; 45 } 46 memset(f,-1,sizeof(f)); 47 cout<<fff(1,n,0)<<endl; 48 return 0; 49 }View Code
[BZOJ1032][P1840] 祖瑪 記憶化搜索 動態規劃