1. 程式人生 > >[BZOJ1032][P1840] 祖瑪 記憶化搜索 動態規劃

[BZOJ1032][P1840] 祖瑪 記憶化搜索 動態規劃

不用 小遊戲 之間 ++ ios 多少 hide 大於 mat

描述 Description
某天,小x在玩一個經典小遊戲——zumo。
zumo遊戲的規則是,給你一段長度為n的連續的彩色珠子,珠子的顏色不一定完全相同,但是,如果連續相同顏色的珠子大於等於k個,這些珠子就會消失。當然,最初的狀態可能不必要直接消掉一些珠子(見樣例)。現在你有無窮個所有顏色的珠子,並且你可以在任意地方插入珠子。
現在提出問題:給你一個固定的狀態,你最少需要用多少個小球,才能將所有的小球消去。

輸入格式 Input Format
第一行是兩個整數,n (1 ≤ n ≤ 100)和k(2 ≤ k ≤5),表示有n個彩色珠子,必須連續有k個以上(包括k個)相同顏色的珠子,這些珠子才會消失。
接下來一行包含n個用空格隔開的整數,每個數在1到100之間,每個數值表示一個珠子的顏色,相同的數字意味著珠子的顏色相同。
輸出格式 Output Format
一個整數,表示最少需要用多少個小球,才能讓所有的小球消失。
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]如果沒值當然要搜索它啊...仙女教母不會自動給你初始化成正確答案的,這是搜索,醒醒!!!!而且搜索之後別忘了記憶化...所以這個鬼畜的東西才叫記憶化搜索... 歡迎神犇捉蟲...雖然神犇看這麽簡單的題估計題解都不願意寫... 因為校對無能所以真的有什麽錯誤我不負責任... 代碼 技術分享
 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] 祖瑪 記憶化搜索 動態規劃