[bzoj1068]压缩
用f[i][j][0/1]表示区间[i,j],i之前有没有M的最少需要多少个字符,然后分两种情况:1.可以分为两个,转移到dp[l][mid][0]+1;2.枚举断点,但当前面有M时,后面的这个不能重复,因此只能写成r-k
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 int f[105][105][2]; 5 char s[105]; 6 bool pd(int l,int r){ 7 if (mid-l+1!=r-mid)return 0; 8 for(int i=0;i<=mid-l;i++) 9 if (s[i+l]!=s[mid+i+1])return 0; 10 return 1; 11 } 12 int dfs(int l,int r,int p){ 13 if (f[l][r][p])return f[l][r][p]; 14 int ans=r-l+1; 15 if (pd(l,r))ans=dfs(l,mid,0)+1; 16 for(int i=l;i<r;i++)ans=min(ans,dfs(l,i,p)+r-i); 17 if (p) 18 for(int i=l;i<r;i++)ans=min(ans,dfs(l,i,1)+dfs(i+1,r,1)+1); 19 return f[l][r][p]=ans; 20 } 21 int main(){ 22 scanf("%s",s); 23 for(int i=0;s[i];i++)f[i][i][0]=f[i][i][1]=1; 24 printf("%d",dfs(0,strlen(s)-1,1)); 25 }