hdu 2476 区间dp

题意:给一个串s,一个串t。将s粉刷成t   ,每次可以粉刷一个区间,将一个区间的字母粉刷成一个相同,最少粉刷需要多少次。

 

思路:区间dp

 

假设我们没有串s,而 将 另一个与 t 完全不相同的串粉刷成t。

这样我们对t进行一个处理,dp[i][j]表示从i到j需要粉刷多少次。这个区间dp并不难。

 

由于可能有s[i]=t[i]导致的不必要的粉刷,处理完t之后,就可以对s,t之间相同的字符处理了。

假设 f[j]  是s->t的最优数目,如果s[j+1]==t[j+1], 那么f[j+1]就不必+1粉刷了,f[j+1]=f[j];

但是如果s[j+1]!=t[j+1],如何进行更新?

考虑再把他分段,分成[1,k][k+1,j]两个区间

[1,k]的最佳情况是f[k],[k+1,j]就是dp[k+1][j];

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) v.begin(),v.end()
#define mem(a) memset(a,0,sizeof(a))

const int N =103;

const ll mod =1e9+7;
const int INF = 1e9+4;
const double eps = 1e-7;

char s[N],t[N];
int dp[N][N];
int f[N];

int main(){

    while(scanf("%s %s",s+1,t+1)!=EOF){

        int n = strlen(s+1);

        for(int i=1;i<=n;++i)
            for(int j=i+1;j<=n;++j)
            dp[i][j]=INF;

        for(int i=1;i<=n;++i)
            dp[i][i]=1;

        for(int i=1;i<=n;++i)
            f[i]=INF;

        for(int len=1;len<n;++len){
            for(int i=1;i+len<=n;++i){
                int j =i+len;
                dp[i][j] = dp[i+1][j]+(t[i]!=t[i+1]);
                for(int k=i+1;k<=j;++k){
                    if(t[i]==t[k])
                    dp[i][j]= min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
                }
            }
        }

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

    }

    return 0;
}

 

posted on 2019-01-22 20:18  Helpp  阅读(132)  评论(0编辑  收藏  举报

导航