HDU6212 Zuma

CII.HDU6212 Zuma

一眼区间DP。

首先,我们将串压缩(即将相同颜色的相邻珠子合并)。记\(col_i\)为位置\(i\)的颜色,\(sz_i\)为位置\(i\)的珠子数。

我们设\(f[i,j]\)表示消去区间\([i,j]\)中所有东西的最小步数。

则有:

\[f[i,j]=\min\begin{cases}3-sz_i&|i=j\\f[i,k]+f[k+1,j]&|i\leq k<j\\f[i+1,j-1]+\max(0,3-sz_i-sz_j)&|col_i=col_j\\f[i+1,k-1]+f[k+1,j-1]&|col_i=col_j=col_k,(sz_i\neq 2\lor sz_j\neq 2)\land sz_k=1\end{cases} \]

其中,第一条转移是直接补满\(3\)个球;第二条转移是找个地方切一刀;第三条转移是将\(i\)\(j\)最终合并在一起进行消除;第四条转移是将\(i\)\(j\),以及区间中某一个\(k\)合并消除,但需要保证有一种消除顺序可以使得\(k\)可以先在不与某一边一起消掉的前提下消到那一边,然后再合并两边。

时间复杂度\(O(Tn^3)\),需要保证常数。

代码:

#include<bits/stdc++.h>
using namespace std;
int T,n,m,sz[210],f[210][210];
bool col[210];
char s[210];
int main(){
	scanf("%d",&T);
	for(int t=1;t<=T;t++){
		scanf("%s",s+1),m=strlen(s+1),n=0;
		col[1]=s[1]-'0',sz[1]=1,n++;
		for(int i=2;i<=m;i++){
			if(s[i]-'0'==col[n])sz[n]++;
			else n++,col[n]=s[i]-'0',sz[n]=1;
		}
		for(int i=1;i<=n;i++)f[i][i]=3-sz[i];
		for(int l=2;l<=n;l++)for(int i=1,j=i+l-1;j<=n;i++,j++){
			f[i][j]=0x3f3f3f3f;
			for(int k=i;k<j;k++)f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
			if(col[i]!=col[j])continue;
			f[i][j]=min(f[i][j],f[i+1][j-1]+max(0,3-sz[i]-sz[j]));
			if(sz[i]==2&&sz[j]==2)continue;
			for(int k=i+1;k<j;k++)if(col[k]==col[i]&&sz[k]==1)f[i][j]=min(f[i][j],f[i+1][k-1]+f[k+1][j-1]);
		}
		printf("Case #%d: %d\n",t,f[1][n]);
	}
	return 0;
} 

posted @ 2021-03-31 14:10  Troverld  阅读(46)  评论(0编辑  收藏  举报