String painter (区间dp+简单dp)

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

题目大概:

有第一个串,变成第二个串,需要最少多少步操作,每次操作可以把一个任意区间涂成一样的颜色。

思路:

如果直接dp一下,那么会有在两种转移方式,当第一个串的第i个和第二个串的第i个,sum【i】=sum【i-1】.这个比较简单。

但是如果不相等那,如果是sum【i】=sum【i-1】+1;那显然是错误的,如果,刷第i段的时候,可以和前面的某一部分一起刷,那么就会多算一次。

那么怎么算那,可以直接暴力枚举一下,sum【i】=min(sum【i】,sum【j】+dp【j+1】【i】)j 属于(0--i)

这样每次不相等,都从前面枚举一遍。这也是一种套路题,很多题都是这么做。但这道题的最佳dp【j+1】【i】没有给出来。也没有从前面得到。所以只能自己算一下,由空白串到第二个串的最佳刷的次数是多少,用一个区间dp求一下,每到遇到两个相同的颜色,就可以优化一下,一起刷。一直优化到最后。

代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=110;
const int INF=0x3f3f3f3f;
char a[maxn];
char b[maxn];
int dp[maxn][maxn];
int sum[maxn];
int main()
{
    while(~scanf("%s%s",a,b))
    {
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        int n=strlen(a);
        //for(int i=0;i<n;i++)dp[i][i]=1;
        for(int i=1;i<=n;i++)
        {
            for(int l=0;l<n-i+1;l++)
            {
                int r=l+i-1;
                dp[l][r]=dp[l+1][r]+1;
                for(int k=l+1;k<=r;k++)
                {
                    if(b[l]==b[k])
                    dp[l][r]=min(dp[l+1][k]+dp[k+1][r],dp[l][r]);
                }
            }
        }

        for(int i=0;i<n;i++)
        {
            sum[i]=dp[0][i];
        }
        for(int i=0;i<n;i++)
        {
            if(a[i]==b[i])
            {
                sum[i]=sum[i-1];
            }
            else
            {
                for(int j=0;j<=i;j++)
                {
                    sum[i]=min(sum[j]+dp[j+1][i],sum[i]);
                }
            }
        }
        printf("%d\n",sum[n-1]);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/a1046765624/article/details/80662802