String painter

 HDU - 2476 

题目描述

有两个长度相等,都只由小写字母构成的字符串A和B. 现在你有一把充满魔♂力的刷子。使用这把刷子,你可以把字符串中连续的一段区间刷♂成一个相同的字符,例如,对于字符串"vandarkholme",把区间[3,6]刷成'd',可以变成"vanddddholme"。现在你要用这把刷♂子把字符串A变成B,最少要刷多少次?

输入

多组数据,每组数据都有两行:
第一行是字符串A.
第二行是字符串B.
字符串长度不超过100.

输出

在单独的一行中输出结果

样例输入

zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd

样例输出

6
7

好久没写区间dp了

之前写过几道区间dp但是基本思想并不是跟理解

正好今天借机复习一下区间dp

的确区间dp就是不断的进行区间合并而找到最优解

根据本题我们不能直接合并因为之间所需要考虑的状态较多

所以我们分两次进行dp

第一次考虑直接图空色

第二次枚举原来的颜色

#include<bits/stdc++.h>
using namespace std;
char s1[105];
char s2[105];
int dp[105][105];
int f[105];
int main()
{
    while(~scanf("%s",s1+1))
    {
        memset(dp,0x3f,sizeof(dp));
        memset(f,0x3f,sizeof(f));
        scanf("%s",s2+1);
        int n=strlen(s1+1);
        for(int len=0;len<n;len++)
        {
            for(int i=1;i<=n;i++)
            {
                int j=i+len;
                if(len==0)
                {
                    dp[i][j]=1;
                    continue;
                }
                dp[i][j]=min(dp[i][j],dp[i+1][j]+(s2[i]!=s2[i+1]));
                dp[i][j]=min(dp[i][j],dp[i+1][j]+(s2[i]!=s2[j]));
                dp[i][j]=min(dp[i][j],dp[i][j-1]+(s2[j]!=s2[j-1]));
                dp[i][j]=min(dp[i][j],dp[i][j-1]+(s2[j]!=s2[i]));
                for(int k=i+1;k<j;k++)
                {
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                }
            }
        }
//        cout<<dp[1][n]<<" "<<dp[1][1]<<endl;
        f[1]=1;
        f[0]=0;
        for(int i=1;i<=n;i++)
        {

            if(s1[i]==s2[i]) f[i]=f[i-1];
            else
            {
                for(int k=0;k<i;k++)
                {
                    f[i]=min(f[i],f[k]+dp[k+1][i]);
                }
            }
        }
        printf("%d\n",f[n]);
    }
}