String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1853 Accepted Submission(s): 820
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.
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
题意:给两个长度相同的由小写字母组成的字符串A,B。一次操作,可以将A串的一个连续区间变成同一个字母,问把A串变成B串最少需要操作多少次?
题解:贪心的想,对于最优策略,每次操作的区间,只有包含关系,没有交叉的关系。也就是说对于原问题把区间[1,n]的串变成目标串的最少操作次数,假设我们的策略是操作区间[i,j],那么原问题就分割成子问题,求把区间[l,i-1]的串变成目标串的最少操作次数,求把区间[i,j]变成目标串的最少操作次数,求把区间[j+1,r]变成目标串的最少操作次数。也就是说一次操作可以,将原问题分割成几个小的子问题。而子问题是满足无后效性的。所以我们可以用动态规划解决。
用dp[l][r][0...25]表示对于区间[l,r] 该区间的字母全为a或b......z,把该状态变到变到目标状态的最小操作次数。
用dp[l][r][26] 表示对于区间[l,r] 该区间的字母为原A串中的字母,把该状态变到目标状态的最小操作次数。
对于每次操作,我们先解决该区间的第1个字母:
假设该区间的首字母和目标串的相同:
dp[l][r][x]=dp[l+1][r][x];
反之:
1,一次操作只将首字母变到目标状态:
dp[l][r][x]=dp[l+1][r][x]+1。
2,如果B[l]==B[i],我们一次操作可以把区间[l,i]变成字母B[l]:
dp[l][r][x]=dp[l+1][i-1][B[l]-'a]+dp[i+1][r][x]+1;
详情见代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<math.h>
#define nn 110
#define inff 0x3fffffff
#define eps 1e-8
typedef long long LL;
const LL inf64=LL(inff)*inff;
using namespace std;
char a[nn],b[nn];
int dp[nn][nn][27];
bool check(int x,int y)
{
if(y==26)
return a[x]==b[x];
return b[x]-'a'==y;
}
int dfs(int l,int r,int s)
{
if(dp[l][r][s]!=-1)
return dp[l][r][s];
if(l>r)
return 0;
if(l==r)
{
if(check(l,s))
return dp[l][r][s]=0;
return dp[l][r][s]=1;
}
dp[l][r][s]=inff;
if(check(l,s))
return dp[l][r][s]=min(dp[l][r][s],dfs(l+1,r,s));
else
dp[l][r][s]=min(dp[l][r][s],dfs(l+1,r,s)+1);
int i;
for(i=l+1;i<=r;i++)
{
if(b[l]==b[i])
{
dp[l][r][s]=min(dp[l][r][s],dfs(l+1,i-1,b[l]-'a')+dfs(i+1,r,s)+1);
}
}
return dp[l][r][s];
}
int main()
{
int i;
while(scanf("%s%s",a,b)!=EOF)
{
int len=strlen(a);
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(0,len-1,26));
}
return 0;
}