题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476
题意:给出a和b两个字符串,目标是将a变化成b,每次变化可以将任意一段区间的字符全部涂成同一个字符,问最少的变化次数
解题思路:dp[i][j]表示a串中i到j变化成b串需要的最小次数
先在默认a和b串全部不相同的情况下,找出dp关系
for(int k=0;k<len;k++){
for(int i=0;i+k<len;i++){
//默认直接改变
dp[i][i+k]=dp[i+1][i+k]+1;
for(int j=i+1;j<=i+k;j++){
//寻找两端相同字符的情况
if(b[i]==b[j])
dp[i][i+k]=min(dp[i][i+k],dp[i+1][j]+dp[j+1][i+k]);
//dp[i+1][j]中已经有b[i]这种,所以不需要再加上i
}
}
}
然后在a字符串中具体处理,如果已存在a串与b串中某一位置相同,则不需要改变
for(int i=0;i<len;i++) ans[i]=dp[0][i];
for(int i=0;i<len;i++){
if(a[i]==b[i]) //相同时,不需要再改变
ans[i]=ans[i-1];
else{ //不同时候,尽量往前找匹配关系
for(int j=0;j<i;j++){
ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
}
}
}
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
using namespace std;
#define inf 1e9
string a,b;
int dp[120][120];
int ans[120];
int len;
int min(int a,int b){
return a<b? a:b;
}
int main(){
while(cin>>a>>b){
memset(dp,0,sizeof(dp));
len=a.size();
for(int k=0;k<len;k++){
for(int i=0;i+k<len;i++){
dp[i][i+k]=dp[i+1][i+k]+1;
for(int j=i+1;j<=i+k;j++){
if(b[i]==b[j])
dp[i][i+k]=min(dp[i][i+k],dp[i+1][j]+dp[j+1][i+k]); //dp[i+1][j]中已经有b[i]这种,所以不需要再加上i
}
}
}
for(int i=0;i<len;i++) ans[i]=dp[0][i];
for(int i=0;i<len;i++){
if(a[i]==b[i])
ans[i]=ans[i-1];
else{
for(int j=0;j<i;j++){
ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
}
}
}
cout<<ans[len-1]<<endl;
}
return 0;
}