String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6934 Accepted Submission(s): 3357
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
Recommend
题意:给你两个相同长度只包含小写字母的字符串 a 和 b,现在你可以进行多次操作,每次操作选择 a 中连续的一段把该段所有位置变为一个相同的字母,现在问你最少要操作多少次可以把字符串 a 变成 b。
思路:简单的区间dp加上普通的dp,因为我们如果直接考虑把 a 串变成 b 串的化不好操作,因为你不知道那些相同字符串要哪些不要。那我我们就直接考虑从空串变到 b 串所需的最小操作次数(区间dp),再考虑 a,b 中相同字母的情况(普通dp)。
设dp[i][j]为空串的区间(i,j)变成 b 串的区间(i,j)需要的最少操作数。对于空串变成 b 串 ,由于我们可以将一段连续的区间变成相同字母,所以对于dp[i][j],我们可以考虑 i 位置是由(i+1,j)中与 i 位置颜色相同的位置连续涂色(假设当前位置为k,我们直接将(i,k)变成相同的字母)得出的。那么dp[i][j] = min ( dp[i][j] , dp[i+1][k-1] + dp[k+1][j]);
因为我们已经将(i,k)变成相同的字母,此时 i ,k位置已经满足条件了,所以我们只要再考虑(i+1,k-1)和(k+1,j)的情况就行了。
我们求出从空串变到 b 串的操作次数了,那我们现在只要考虑字母相同位置的选择就可以了
代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; char a[110],b[110]; int dp[110][110]; int ans[110]; int main(){ while(scanf("%s%s",a,b)!=EOF){ int len=strlen(a); int cnt=1; for(int i=0;i<len;i++){ dp[i][i]=1; } for(int i=1;i<len;i++){ for(int j=0;i+j<len;j++){ dp[j][i+j]=1e9; for(int k=j;k<=i+j;k++){ if(k!=j&&b[j]==b[k]) dp[j][i+j]=min(dp[j][i+j],dp[j+1][k]+dp[k+1][i+j]); else dp[j][i+j]=min(dp[j+1][i+j]+1,dp[j][i+j]); } //rintf("%d %d %d ",j,i+j,dp[j][i+j]); /*afgadfabb abcacbacc*/ } } for(int i=0;i<len ;i++){ if(a[i]==b[i]){ if(i==0){ ans[i]=0; } else ans[i]=ans[i-1]; } else{ ans[i]=dp[0][i];//ans[i]表示前i位置考虑相同字母时的取值情况 for(int j=0;j<i;j++) ans[i]=min(ans[i],ans[j]+dp[j+1][i]); } //printf("%d %d ",i,ans[i]); } printf("%d ",ans[len-1]); } }