Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6106 Accepted Submission(s): 2937 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:
Output A single line contains one integer representing the answer.
Sample Input zzzzzfzzzzz abcdefedcba abababababab cdcdcdcdcdcd
Sample Output 6 7
Source
Recommend lcy | We have carefully selected several similar problems for you: 2480 2481 2478 2482 2475 |
题目大意:先给你两个字符串,要求用最少的刷漆次数让s1=s2,一次可以把第一个字符串中的一段区间内的所有字母都换成同一个字母
思路:
区间dp中求出s2中每一段,每一小段中的最少刷漆次数用dp[i][j]表示,过程中可以先假设每一段都要有一次的刷漆,
dp[i][j]=dp[i+1][j],随后的话,可以找一找现在小区间内部有没有更小的刷漆方式,也就是找相同的字母,找到了将两个小区间组合成当前取区间的答案即可,
然后对于第1个字符串,我们可以遍历整个字符串如果存在s1s2中有对应位置字母相同的,那么就可以跳过了,这个位置是不用刷漆的,如果不相同,那就要遍历小区间找一个最小的ans了
状态转移方程见代码吧~
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 110
using namespace std;
int dp[maxn][maxn];
int ans[maxn];
char s1[maxn],s2[maxn];
int main()
{
while(scanf("%s%s",s1,s2)!=EOF)
{
int n=strlen(s2);
memset(dp,0,sizeof(dp));
for(int j=0;j<n;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(s2[i]==s2[k])
dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
}
}
}
for(int i=0;i<n;i++)
ans[i]=dp[0][i];
for(int i=0;i<n;i++)
{
if(s1[i]==s2[i])
ans[i]=ans[i-1];
else
{
for(int k=0;k<i;k++)
ans[i]=min(ans[i],ans[k]+dp[k+1][i]);
}
}
cout<<ans[n-1]<<endl;
}
return 0;
}