【[SCOI2007]压缩】区间DP

首先说明,,这个DP状态是从网上抄的(实在没想出来,无奈)--》f[i][j]表示当前已经处理完字符串中的位置i,此时从i向左 第一个M的位置为j 那么我们们就可以比较容易的想到DP方程了 先进行一波预处理搞定可压缩的段 首先1.对于dp[i][j]我们可以什么都不做直接跳到下一个位置,即dp[i+1][j]=d[i][j]+1 2.对于dp[i][i]我们肯定是从前i最小的那个dp状态跳到后面的时候,在后面摆一个M,此时为dp[i][i]=min:dp[i][j]+1 3.对于一般地dp[i][j]能满足的就直接压缩往后刷表就可以了 if:same(i(包含)前j个字符==i后j个字符) dp[i+j][j]=min:dp[i][j]+1 还是太菜了太菜了太菜了。。。

/*1 do nothing : dp[i+1][j]=dp[i][j]+1
2 take 1 M: dp[i][i] = min(dp[i][j])+1
3 find same dp[i+(i-j)][i]=dp[i][j]+1*/


#include<bits/stdc++.h> 
using namespace std;
 char aha[55]; bool sa[55][55]; 
int dp[55][55],n; 
int main() 
{ 
        int i,j,k;
        scanf("%s",aha+1);
	n=strlen(aha+1);
	for(i=1; i<=n; i++)
	{
		for(j=1; i-j+1>=1&&i+j<=n; j++)
		{
			sa[i][j]=1;
			for(k=i-j+1; k<=i; k++)
			{
				if(aha[k]!=aha[k+j])
				{
					sa[i][j]=0;
					break;
				}
			}
		}
	}
	memset(dp,0x3f3f3f3f,sizeof dp);
	dp[0][0]=1;
	for(i=0; i<=n; i++)
	{
		for(j=0; j<=i; j++)
		{
			dp[i][i]=min(dp[i][i],dp[i][j]+1);
			dp[i+1][j]=min(dp[i][j]+1,dp[i+1][j]);
			if(sa[i][i-j])
			{
				dp[i+(i-j)][j]=min(dp[i+(i-j)][j],dp[i][j]+1);
			}
		}
	}
	int ans=0x3f3f3f3f;
	for(i=0; i<=n; i++) ans=min(ans,dp[n][i]);
	printf("%d",ans-1);
}

 

posted @ 2018-03-24 01:08  Newuser233  阅读(5)  评论(0)    收藏  举报