HDU 2476 String painter

区间DP。

区间DP专题做到现在,发现这题思路最难......自己想出来方法正确性应该没问题,但时间复杂度高达26000000..都不敢写了。

最终看了题解,发现真的不在我目前能力范围之内......编码量很少,但思维成分高。。。

首先:dp[i][j]表示把[i,j]空白串刷成t串[i,j]所需的最少操作次数,可以区间DP得到

f[i]表示把s串[0,i]刷成t串[0,i]所需最少操作次数,根据上面区间DP的结果,可以线性DP得到。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn=100+10;
char s[maxn],t[maxn];
int dp[maxn][maxn];
int f[maxn];
int len;

void init()
{
    len=strlen(s);

    for(int i=0;i<len;i++)
        for(int j=0;j<len;j++)
            dp[i][j]=j-i+1;
}

void work()
{
    for(int i=1;i<=len;i++)
    {
        for(int j=0;j<len;j++)
        {
            int st=j,en=st+i-1;
            if(en>=len) continue;
            dp[st][en]=min(dp[st][en],1+dp[st+1][en]);
            for(int k=st+1;k<=en;k++)
                if(t[st]==t[k])
                    dp[st][en]=min(dp[st][en],dp[st+1][k]+dp[k+1][en]);
        }
    }

    if(s[0]==t[0]) f[0]=0;
    else f[0]=1;

    for(int i=1;i<len;i++)
    {
        f[i]=dp[0][i];
        for(int k=0;k<i;k++) f[i]=min(f[i],f[k]+dp[k+1][i]);
        if(s[i]==t[i]) f[i]=min(f[i],f[i-1]);
    }
    printf("%d
",f[len-1]);
}

int main()
{
    while(~scanf("%s%s",s,t))
    {
        init();
        work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5226317.html