[HDU6212]Zuma
题目大意:
祖玛游戏。
给你一个01串,你可以往里面加一些0或1,如果连续的0或1超过3个,那么就可以消去。问消去所有的珠子至少要加几个珠子。
思路:
区间DP。
首先把原来的01串,改成存储连续的同种颜色的珠子有几个。
考虑只有一种珠子时,f[i][j]=3-a[i];
若当前区间有多种颜色的珠子,分为以下几种情况:
1.由两个区间合并而来,f[i][j]=std::min(f[i][j],f[i][k]+f[k+1][j]);
2.如果当前区间内有奇数个连续的同色珠子块,又分为以下2种情况:
1).消去中间的块以后,两边的块合并:f[i][j]=std::min(f[i][j],f[i+1][j-1]+(a[i]+a[j]==2));
2).分别消去中间两个块后,左、中、右的块合并:f[i][j]=std::min(f[i][j],f[i+1][k-1]+f[k+1][j-1])。
1 #include<cstdio> 2 #include<cctype> 3 #include<algorithm> 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int N=201; 12 char s[N]; 13 int a[N],f[N][N]; 14 int main() { 15 int T=getint(); 16 for(register int t=1;t<=T;t++) { 17 scanf("%s",s); 18 a[0]=a[1]=1; 19 for(register int i=1;s[i];i++) { 20 if(s[i]==s[i-1]) { 21 a[a[0]]++; 22 } else { 23 a[++a[0]]=1; 24 } 25 } 26 for(register int i=1;i<=a[0];i++) { 27 a[i]=std::min(a[i],2); 28 } 29 for(register int j=1;j<=a[0];j++) { 30 for(register int i=j;i;i--) { 31 if(i==j) { 32 f[i][j]=3-a[i]; 33 continue; 34 } 35 f[i][j]=(j-i+1)<<1; 36 for(register int k=i;k<j;k++) { 37 f[i][j]=std::min(f[i][j],f[i][k]+f[k+1][j]); 38 } 39 if((j-i)&1) continue; 40 f[i][j]=std::min(f[i][j],f[i+1][j-1]+(a[i]+a[j]==2)); 41 if(a[i]+a[j]<=3) { 42 for(register int k=i+2;k<j-1;k++) { 43 if(a[k]!=1) continue; 44 f[i][j]=std::min(f[i][j],f[i+1][k-1]+f[k+1][j-1]); 45 } 46 } 47 } 48 } 49 printf("Case #%d: %d\n",t,f[1][a[0]]); 50 } 51 return 0; 52 }