【uva1437】String painter

题目描述

有两个用小写英文字母组成的等长字符串。你有一个强大的字符串刷子,在这把刷子的帮助下,你可以将一个字符串的一个字串中的字符全部刷成任何你想要的字符。也就是说,用刷子刷过的字串就变成用同一个字母组成的了。现在你想要用这一把刷子把字符串A刷成B,而且要求刷的次数最少。


输入

输入包含多组数据,每组数据由两行组成:

第一行一个字符串A,第二行一个字符串B.

在同一组数据中,保证A和B长度相等。


输出

对于每组数据,单独的一行输出刷的最小次数。


样例输入

zzzzzfzzzzz

abcdefedcba

abababababab

cdcdcdcdcdcd


样例输出

6

7



题解

区间dp,是 CQOI2017涂色 的增强版。首先我们还是先求出 涂色 那道题的dp[ i ][ j ],这道题把它叫 f [ i ][ j ] 。但在这道题里,我们知道有些地方本来就是匹配的,不用改变,所以我们设 dp[ i ] 表示a串中从1到i号位置的最少涂色次数,先初始化 dp[ i ] = f [ 1 ][ i ] 。枚举 i ,当 a[ i ] == b[ i ] ,dp [ i ] = dp[ i-1 ] ( i 位置不用涂色) ,否则,枚举k,dp[ i ] = dp[ k ] + f [ k+1 ][ i ] 。 dp[ n ] 就是答案。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=100+5;

int f[maxn][maxn],dp[maxn],n;
char a[maxn],b[maxn];

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    while(cin>>a+1>>b+1){
        memset(f,127,sizeof(f));
        memset(dp,0,sizeof(dp));
        n=strlen(a+1);
        for(int i=1;i<=n;i++) f[i][i]=1;
        for(int len=2;len<=n;len++)
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            if(b[i]==b[j]) f[i][j]=min(f[i][j-1],f[i+1][j]);
            else for(int k=i;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
        }
        for(int i=1;i<=n;i++){
            dp[i]=f[1][i];
            if(a[i]==b[i]) dp[i]=(i==1?0:dp[i-1]);
            else for(int k=1;k<i;k++) dp[i]=min(dp[i],dp[k]+f[k+1][i]);
        }
        cout<<dp[n]<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/rlddd/p/9544184.html