HDU 2476 String painter

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?
InputInput 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.  
OutputA single line contains one integer representing the answer.Sample Input
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output
6

7

自己也是看题解做的,就难说思路的来源了,这里整理一下过程。

大体的思路是,直接将已知串转化成目标串存在困难,先考虑空白串转化成目标串所需要的最少次数,然后再通过已知串中对应位置和目标串中的元素是否相同来优化。

将空白串转化的最少次数,思考用区间dp来解决。如果从d[i+1][j]转移到dp[i][j]时,s[i]!=s[j]那么我们就可以用区间dp的基础方法来处理它,遍历ij中间的所有值作为中间点看看是否有更短路,但是要记得先让它比之前的数值加1。这里难考虑的是,为什么是从dp[i+1][j]+1,而不是dp[i][j-1]?当s[i]==s[j],这个时候从哪个方向加上来,由于左右具有对称性(首元素都是同样的),应该数值是相同的;当s[i]!=s[j],这个时候我们的中间点在取值的时候是从i+1开始取值,这样的话dp[i][i]+dp[i+1][j]就是没有考虑到的,而dp[i][j-1]+dp[j][j]是已经考虑到的。

处理完了空白串转移到目标串的操作以后,进行对位优化。当a[i]==b[i],这一步是不用刷的,而原dp数组中可能刷了也可能没刷,解决的办法是,此时dp[0][i]==d[0][i-1],我们从0到n-1逐个元素增加上来,每一次增加区间,都要从开头设置中间点查看优化的方案,dp[0][i]=min(dp[0][i],dp[0][k]+dp[k+1][i]),这样保证dp[0][i]的数组始终是最新的答案。为了便于思路,也可以设置一个ans[]数组,保存dp[0]这个数组。这么操作的原理暂时未很清楚,先了解有这么一个方法吧。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    char a[110],b[110];
    int dp[110][110],res[110];
    while(~scanf("%s%s",b,a))
    {
        int n=strlen(a);
        memset(dp,0,sizeof(dp));
        memset(res,0,sizeof(res));
        for(int i=0;i<n;i++)
            dp[i][i]=1;
        for(int len=1;len<n;len++)
        {
            for(int i=0,j=i+len;j<n;i++,j++)
            {
                dp[i][j]=dp[i+1][j]+(a[i]==a[j]?0:1);//从右向左更新,这是把右半部分作为已经完成的更新
                for(int s=i+1;s<j;s++)
                    if(a[i]==a[s]) dp[i][j]=min(dp[i][j],dp[i][s]+dp[s+1][j]);//有相同的就有了优化的可能性
            }
        }
        for(int i=0;i<n;i++)
            {
                res[i]=dp[0][i];

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


猜你喜欢

转载自blog.csdn.net/xuzonghao/article/details/80754978