hdu2476(区间dp+dp)

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
2008 Asia Regional Chengdu
 
Recommend
lcy   |   We have carefully selected several similar problems for you:   2480  2481  2478  2482  2475 
 
题意:给你两个相同长度只包含小写字母的字符串 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
#include
#include
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){
            dp[i][i]=1;
        }        
        for(int i=1;i){
            for(int j=0;i+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\n",j,i+j,dp[j][i+j]);
                /*afgadfabb
                abcacbacc*/
            }            
        }
        for(int i=0;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)
                ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
            }
            //printf("%d %d\n",i,ans[i]);
        }
        printf("%d\n",ans[len-1]);
        
    }
}

 

你可能感兴趣的:(hdu2476(区间dp+dp))