【[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);
}

浙公网安备 33010602011771号