HDU-2476 String painter(区间DP)

 

String painter

Time 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:
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

扫描二维码关注公众号,回复: 2743349 查看本文章
 

Sample Output

 

6 7

 

Source

2008 Asia Regional Chengdu

 

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;
}

猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/81508122