1068: [SCOI2007]压缩

题解:

区间DP

考虑状态的设计:

\(dp[i][j][0/1]\)表示原字符串的\(i-j\)区间有无在中间加\(M\)。并且默认在\(i\)之前加入\(M\)压缩后的最小长度,显然有转移:

\[dp[i][j][0]=\min_{k=i}^j(dp[i][k][0]+j-k) \]

\[dp[i][j][0]=min(dp[i][j][0],dp[i][\frac {i+j} 2 ][0]+1)\ \ (s[i\ to\ \frac {i+j} 2]==s[\frac {i+j} 2 +1 \ to \ j]) \]

\[dp[i][j][1]=\min_{k=i}^{j-1}(min(dp[i][k][0],dp[i][k][1])+1+min(dp[k+1][j][0],dp[k+1][j][1])) \]

代码:

#include<bits/stdc++.h>

using namespace std;

namespace Tzh{

	const int maxn=55;
	char s[maxn];
	int dp[maxn][maxn][2],n;
	
	void work(){
		scanf("%s",s+1); n=strlen(s+1);
		memset(dp,0x3f3f3f3f,sizeof(dp));
		for(int i=1;i<=n;i++) dp[i][i][0]=1;
		for(int l=2;l<=n;l++)
			for(int i=1,j=i+l-1;j<=n;i++,j++){
				for(int k=i;k<j;k++) 
					dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+j-k);
				if(~l&1){
					for(int a=i,b=i+l/2;b<=j;a++,b++)
						if(s[a]!=s[b]) goto end;
					dp[i][j][0]=min(dp[i][j][0],dp[i][i+l/2-1][0]+1);
				} 
				end:
				for(int k=i;k<j;k++) 
					dp[i][j][1]=min(dp[i][j][1],min(dp[i][k][0],dp[i][k][1])+
								1+min(dp[k+1][j][0],dp[k+1][j][1]));
			}
		printf("%d",min(dp[1][n][1],dp[1][n][0]));
		return ;
	}
}

int main(){
	Tzh::work();
	return 0;
}

posted @ 2018-09-05 08:56  Jack_the_Ripper  阅读(98)  评论(0编辑  收藏  举报