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