[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 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11790620.html