hdu 2476 题解

Posted donkey2603089141

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 2476 题解相关的知识,希望对你有一定的参考价值。

题目

题意

给出两个字符串 $ s1,s2 $,每次操作可以使一段连续的子串全变成一个字母,问最少多少次操作可以使 $ s1 $ 变为 $ s2 $.

例如 $ zzzzzfzzzzz $,长度为 $ 11 $ ,我们就将下标看做 $ 1~11 $

先将 $ 1-11 $ 刷一次,变成 $ aaaaaaaaaaa $

$ 2-10:abbbbbbbbba $

$ 2-8:abcccccccba $

$ 3-7:abcdddddcba $

$ 4-6:abcdeeedcab $

$ 5:abcdefedcab $

这样就 $ 6 $ 次,变成了 $ s2 $ 串了

第一眼看到这题,我就想到了这个

题意给出一个字符串,要求将一块空白木板刷成指定字符串,问最少操作次数(规则如上

我们可以定义 $ f[i][j] $ 表示从 $ i $ 刷到 $ j $ 的最少操作次数

转移方程

$ f[i][j]=f[i+1][j]+1 $

$ if(s1[i]==s1[k]) f[i][j]=min(f[i][j],f[i+1][j]+f[k+1][j]) $

$ i+1<=k>=j $

代码

#include<bits/stdc++.h>
using namespace std;
char str1[105];
int dp[105][105],ans[105];
int main(){
    scanf("%s",str1+1);
    int n=strlen(str1+1);
    memset(dp,0,sizeof(dp));
    for(int j=1;j<=n;++j){//枚举终点
        for(int i=j;i;--i){//起点
            dp[i][j]=dp[i+1][j]+1;//直接刷
            for(int k=i+1;k<=j;++k){
                if(str1[i]==str1[k]){//相同就枚举断点
                    dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
                }
            }
        }
    }
    printf("%d",dp[1][n]);
    return 0;
} 

仔细一想我们可以发现如果 $ s1,s2 $ 没有一个相同的字母那么不就是上面那题吗?

我们可以很容易发现,如果有相同字母那么就有可能缩小次数。

我们可以定义 $ f[i][j] $ 意义同上 $ ans[i] $ 表示到第 $ i $ 个字母所需要的最少次数

$ f $ 转移方程同上

$ if(str1[i]==str2[i]) ? ans[i]=ans[i-1] $ 字母相同直接转移

$ else ?ans[i]=min(ans[i],ans[j]+dp[j+1][i]) $ 字母不同考虑改变

$ 1<j<i $

代码

#include<bits/stdc++.h>
using namespace std;
char str1[105];
char str2[105];
int dp[105][105],ans[105];
int main(){
    while(~scanf("%s %s",str1+1,str2+1)){
        int n=strlen(str1+1);
        memset(dp,0,sizeof(dp));
        for(int j=1;j<=n;++j){
            for(int i=j;i;--i){
                dp[i][j]=dp[i+1][j]+1;
                for(int k=i+1;k<=j;++k){
                    if(str2[i]==str2[k]){
                        dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
                    }
                }
            }
        }
        for(int i=1;i<=n;++i) ans[i]=dp[1][i];
        for(int i=1;i<=n;++i){
            if(str1[i]==str2[i]) ans[i]=ans[i-1];
            else{
                for(int j=1;j<i;++j){
                    ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
                }
            } 
        }
        printf("%d
",ans[n]);
    }
    return 0;
} 

以上是关于hdu 2476 题解的主要内容,如果未能解决你的问题,请参考以下文章

String painter (hdu 2476 DP好题)

HDU 2476 String painter

HDU-2476 String painter 区间DP

hdu 2476 String Painter

HDU 2476 String painter (区间DP)

HDU2476