String painterTime Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5954 Accepted Submission(s): 2843 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 |
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[105][105],res[105]; //dp[i][j]表示i~j这个区间涂的最少次数,res[i]表示到str[i]为止的字符串的最少涂的次数
char str1[105],str2[105];
int main()
{
int i,j,k,n;
int len;
int l,r;
while(scanf("%s%s",str1,str2)!=EOF)
{
n=strlen(str2);
memset(dp,0,sizeof(dp));
//先考虑str1是空串的情况。
for(len=1;len<=n;len++) //区间DP 用长度这个for 引出l,r;
{ //len越小,left能到达的就越远
//还能发现一点,当右区间小于左区间的DP就是0
//区间DP就是从长度短的每个区间dp到每个区间长的
for(l=0;l<n-len+1;l++) //字符串下标从0开始,l是能够到达最右边的
{
r=l+len-1; //r是根据长度定的,如果长度为1的话,right一定是等于left的
if(r<l+1) //这个不过是一种修复,在思考动归的时候不用考虑
dp[l][r]=1; //区间DP的预处理就是把最简单的一种方式记录到DP数组中。
else //额,不只是区间DP要预处理,普通DP也要预处理的呀,讲了一堆废话。
dp[l][r]=dp[l+1][r]+1;
for(k=l+1;k<=r;k++) //k的区间DP,总是在简单的预处理之后,进行的区间DP。
{ //k不一定就是从l开始,到r-1结束,也可以是l+1开始的,也可以到r结束,
//由状态转移决定。
if(str2[l]==str2[k])
dp[l][r]=min(dp[l][r],dp[l+1][k]+dp[k+1][r]); //不用+1,因为这是在预处理后的DP,出现相同就少涂一次
} //这个转移方程是自己探索发现的,这样就减少了一次涂色的次数
}
}
for(i=0;i<n;i++)
res[i]=dp[0][i]; //这是对空串而言的。这样的预处理也十分正常
for(i=0;i<n;i++)
{
if(str1[i]==str2[i])
{
if(i==0)
res[i]=0;
else
res[i]=res[i-1];
}
else
{
for(j=0;j<i;j++)
res[i]=min(res[i],res[j]+dp[j+1][i]); //普通dp与区间dp结合
}
}
printf("%d\n",res[n-1]);
}
return 0;
}