【HDU】2476String painter-区间dp最少刷漆

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

题目大意:先给你两个字符串,要求用最少的刷漆次数让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;
}

猜你喜欢

转载自blog.csdn.net/wentong_Xu/article/details/82317668