hdu2476

/*
dp[l][r]表示将任意串的[l,r]刷成s2样子的最小代价
ans[i]表示将s1的前i位刷成s2的代价
按照区间dp的常用做法,dp[l][r]的状态由dp[l][k],dp[k+1][r]决定
若s2[l]==s2[k],那么在刷k的时候也能刷到l,dp[l][r]=min(dp[l][r],dp[l+1][k]+dp[k+1][r])
但是有可能所有的s[k]!=s[l],即s2[l]要被单独刷一次,那么dp[l][r]要被赋初值dp[l][r]=1+dp[l+1][r] 
第二步计算ans数组,若s1[i]==s2[i],那么第i位就不用刷,即ans[i]=ans[i-1]
否则ans[i]=min(ans[i],ans[k]+dp[k+1][i]); 
*/
#include<bits/stdc++.h>
using namespace std;
char s1[200],s2[200];
int dp[200][200],ans[200],n;

int main(){
    while(scanf("%s%s",s1,s2)==2){
        n=strlen(s1);
        memset(dp,0,sizeof dp);
        for(int r=0;r<n;r++)//右边界 
            for(int l=r;l>=0;l--){//左边界依次拓展 
                dp[l][r]=dp[l+1][r]+1;
                for(int k=l+1;k<=r;k++)    
                    if(s2[l]==s2[k])//只要将刷左子区间和刷右子区间的值合并即可 
                         dp[l][r]=min(dp[l][r],dp[l+1][k]+dp[k+1][r]);
            }
        for(int i=0;i<n;i++)
            ans[i]=dp[0][i];
        for(int i=0;i<n;i++)
            if(s1[i]==s2[i])ans[i]=ans[i-1];
             else {
                 for(int j=0;j<i;j++)
                     ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
             }
        printf("%d\n",ans[n-1]);
    }
}

 

posted on 2019-01-25 14:10  zsben  阅读(483)  评论(0编辑  收藏  举报

导航