题意:给两个长度相等的字符串s,t,每步可以把s的一个连续子串刷成同一个字母,问至少需要多少步从才能把s变成t。
思路:借鉴了别人的思想 :HyogaHyoga,首先求出一个空串(长度等于t不过元素为空)需要多少步才能变成t,设d[i][j]为从i到j至少需要多少步,d[i][j]的下一个状态显然有d[i+1][j]和d[i][j-1],当t[i]=t[j]时d[i][j]=d[i+1][j],不等于时还要加个1,如果存在一个k(i<k<j)使得t[i]=t[k]或者t[j]=t[k],那么d[i][j]=min(d[i][j],d[i][k-1]+d[k+1][j]),可用记忆化搜索搞定d数组,然后再求答案f数组,设f[i]为从0到i,s[i]经过最少f[i]步可以变成t[i],很容易发现当s[i]=t[i]时,f[i]=f[i-1],否则f[i]=min{d[0][i],f[j]+d[j+1][i]}
#include<stdio.h> #include<string.h> #define max(x,y) x>y?x:y #define min(x,y) x<y?x:y char s[1000],t[1000]; int d[101][101],f[101]; int dp(int i,int j) { if(d[i][j]) return d[i][j]; if(i==j) return d[i][j]=1; int temp=(t[i]==t[j]?0:1); d[i][j]=min(dp(i+1,j)+temp,dp(i,j-1)+temp); for(int k=i+1;k<j;k++) { if(t[k]==t[i]) d[i][j]=min(d[i][j],dp(i+1,k)+dp(k+1,j)); if(t[k]==t[j]) d[i][j]=min(d[i][j],dp(i,k-1)+dp(k+1,j)); } return d[i][j]; } int main() { while(~scanf("%s%s",s,t)) { int i,j,k; memset(d,0,sizeof(d)); k=strlen(t); dp(0,k-1); if(s[0]==t[0]) f[0]=0; else f[0]=1; for(i=1;i<k;i++) { f[i]=d[0][i]; if(s[i]==t[i]) f[i]=f[i-1]; else for(j=0;j<i;j++) f[i]=min(f[j]+d[j+1][i],f[i]); } printf("%d\n",f[k-1]); } }