String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4626 Accepted Submission(s): 2171
Problem Description
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?
Input
Input contains multiple cases. Each case consists of two lines:
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
Output
A single line contains one integer representing the answer.
Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output
6
7
Source
2008 Asia Regional Chengdu
Recommend
lcy
题意:
把不同字母看成看不同颜色,那么问题就是每次可以用一种颜色画一段区间
先考虑最极端的情况
把a看成是空白的(也可以理解为a与b在同一个位置完全没有公共颜色,需要全部重新涂颜色),那么把ab画成相同颜色需要的最小步数可以通过和Halloween Costumes 一样的方法处理出来,即为直接区间DP(下面会讲)
为什么?
如果C里的衣服看成颜料,每次穿衣服表示用这种颜色,每个时间点在最外面的只有一件衣服,按照时间把最外面衣服的颜色排成一排
PS放在最前面:while(~scanf(“%s%s”,a+1,b+1))
len=strlen(a+1);
个人习惯字符串开始下标为1,下标为0的也类似,改一下就可以了
for(int j=1;j<=len;++j)
{
for(int i=j;i>0;–i)
{
dp[i][j]=dp[i+1][j]+1;
for(int k=i+1;k<=j;++k)
if(b[i]==b[k])dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);
}
}
这样我们处理出来了所有[L,R]区间要变成和b一样的最小代价
这有什么用?
用于推广到一般情况
考虑a,b在某些位置有共同颜色的情况
只需要去掉a,b颜色相同的位置带来的影响
怎么去掉?
如果a[i]之前与b[i]都完全不同,那么1~i-1的代价就是之前dp[1][i-1]
重新开一个数组ans[i],记录a到第i个位置画成和b一个样子需要的最小代价,初始值i->1 to length ans[i]=dp[1][i];
每个位置有a[i]==b[i],a[i]!=b[i]两种情况
<1>a[i]==b[i]那就很明显了,这个位置存在与否根本不影响现在求第i位的答案,因为需要的代价和做到第i-1位是一样的ans[i]=ans[i-1]
<2>a[i]!=b[i]
如果不相等,那么是不是和之前那个问题一样了?要求[1,i]的最小代价,ans[i]=min{ans[j]+F[j+1][i]},1<=j
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100+5;
char a[maxn],b[maxn];
int dp[maxn][maxn];
int len,ans[maxn];
int main()
{
while(~scanf("%s%s",a+1,b+1))
{
len=strlen(a+1);
memset(dp,0,sizeof(dp));
for(int j=1;j<=len;++j)
{
for(int i=j;i>0;--i)
{
dp[i][j]=dp[i+1][j]+1;
for(int k=i+1;k<=j;++k)
if(b[i]==b[k])dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]);
}
}
for(int i=1;i<=len;++i)ans[i]=dp[1][i];
for(int i=1;i<=len;++i)
{
if(a[i]==b[i])ans[i]=ans[i-1];
else
{
for(int j=1;j<i;++j)
ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
}
}
printf("%d\n",ans[len]);
}
return 0;
}