挺有难度的一道题,区间DP,我参考别人的代码,自己加了写注释
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=100+10;
const int INF=0x7f7f7f7f;
char a[N],b[N];
int d[N][N],ans[N];
int main()
{
while(~scanf("%s%s",a,b))
{
int l=strlen(b);
memset(d,0,sizeof(d));
for(int i=0;i<l;i++)
d[i][i]=1;
//先求将一个空串转换成b需要的最少步数,d[l][r]代表l~r区间
for(int i=1;i<l;i++)
for(int j=0;j+i<l;j++)
{//如果左右端相同,可以开始直接将整个区间刷为一色,不需要再加一步
d[j][j+i]=d[j+1][j+i]+(b[j]==b[j+i]?0:1);
for(int k=j+1;k<j+i;k++) //遍历一遍区间
if(b[j]==b[k]) //如果和左端相同,可以考虑拆分为两个区间,可能减少步数
d[j][j+i]=min(d[j][j+i],d[j+1][k]+d[k+1][j+i]);
}
//ans[i]代表将前i位a转换成b需要的步数
ans[0]=(a[0]==b[0]?0:1); //第一位相同则ans[0]为0
for(int i=1;i<l;i++)
{
ans[i]=d[0][i]; //初始值为将空串转化为b串0~i的步数
if(a[i]==b[i]) //如果这一位相同,可以不管,是前一位的步数
ans[i]=min(ans[i],ans[i-1]);
for(int j=0;j<i;j++) //遍历区间0~i,考虑把前j+1~i为作为空串处理
ans[i]=min(ans[i],ans[j]+d[j+1][i]);
}
printf("%d\n",ans[l-1]);
}
return 0;
}