http://acm.hdu.edu.cn/showproblem.php?pid=2476
String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6863 Accepted Submission(s): 3330
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
题意:有两个字符串,A串和B串,每次可以对A串一个区间进行涂改,使该区间所有字母变成任意一种字母,求使A串变成B串需要的最少操作次数
题解:首先考虑一个简化的问题,把一个空串涂改成B串需要的操作数,显然可以通过最基本的区间dp进行解决,转移方程为if(B[i]==B[k])dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);else dp[i][j]=min(dp[i][j],min(dp[i][k]+dp[k+1][j],dp[i][k-1]+dp[k][j]));然后考虑A串不是空串,那么如果A[i]==B[i],则有ans[i]=ans[i-1],如果A[i]!=B[i],那么ans[i]=min(ans[j]+dp[j][i])。
普通的循环迭代版本
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl; 4 char ch[105],ch2[105]; 5 int dp[105][105],ans[105]; 6 const int inf=1e8; 7 int main(){ 8 while(scanf("%s",ch+1)!=EOF){ 9 scanf("%s",ch2+1); 10 int len=strlen(ch+1); 11 for(int i=1;i<=len;i++){ 12 for(int j=1;j<=len;j++){ 13 if(i>j)dp[i][j]=0; 14 else if(i==j)dp[i][j]=1; 15 else dp[i][j]=inf; 16 } 17 } 18 for(int i=2;i<=len;i++){ 19 for(int j=1;j+i-1<=len;j++){ 20 for(int k=j+1;k<=j+i-1;k++){ 21 if(ch2[j]==ch2[k])dp[j][j+i-1]=min(dp[j][j+i-1],dp[j][k-1]+dp[k+1][j+i-1]); 22 else dp[j][j+i-1]=min(dp[j][j+i-1],min(dp[j][k]+dp[k+1][j+i-1],dp[j][k-1]+dp[k][j+i-1])); 23 } 24 } 25 } 26 for(int i=1;i<=len+1;i++){ 27 ans[i]=inf; 28 } 29 ans[1]=0; 30 for(int i=1;i<=len;i++){ 31 if(ch[i]==ch2[i]){ 32 ans[i+1]=min(ans[i+1],ans[i]); 33 } 34 else{ 35 for(int j=1;j<=i;j++){ 36 ans[i+1]=min(ans[i+1],ans[j]+dp[j][i]); 37 } 38 } 39 } 40 printf("%d\n",ans[len+1]); 41 } 42 return 0; 43 }
记忆化搜索版本(注意由于sol(1,len)只能保证dp[1][len]被更新,而不能保证所有的dp[i][j]被遍历到,所以需要使用n^2次sol(i,j)保证所有dp[i][j]都被更新了而不再是初始值)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define debug(x) cout<<"["<<#x<<"]"<<" is "<<x<<endl; 4 char ch[105],ch2[105]; 5 int dp[105][105],ans[105]; 6 const int inf=1e8; 7 int sol(int l,int r){ 8 if(dp[l][r]!=0x3f3f3f3f)return dp[l][r]; 9 if(l>r)return dp[l][r]=0; 10 if(l==r)return dp[l][r]=1; 11 for(int k=l+1;k<=r;k++){ 12 if(ch2[k]==ch2[l]){ 13 dp[l][r]=min(dp[l][r],sol(l+1,k)+sol(k+1,r)); 14 } 15 else{ 16 dp[l][r]=min(dp[l][r],sol(l+1,r)+1); 17 } 18 } 19 return dp[l][r]; 20 } 21 int main(){ 22 while(scanf("%s",ch+1)!=EOF){ 23 scanf("%s",ch2+1); 24 int len=strlen(ch+1); 25 memset(dp,0x3f3f3f3f,sizeof(dp)); 26 for(int i=1;i<=len;i++){ 27 for(int j=i;j<=len;j++){ 28 sol(i,j); 29 } 30 } 31 // sol(1,len); 32 for(int i=1;i<=len+1;i++){ 33 ans[i]=0x3f3f3f3f; 34 } 35 ans[1]=0; 36 for(int i=1;i<=len;i++){ 37 if(ch[i]==ch2[i]){ 38 ans[i+1]=min(ans[i+1],ans[i]); 39 } 40 else{ 41 for(int j=1;j<=i;j++){ 42 ans[i+1]=min(ans[i+1],ans[j]+dp[j][i]); 43 } 44 } 45 } 46 printf("%d\n",ans[len+1]); 47 } 48 return 0; 49 }