UVALive 4394 String painter

题目大意:给你两个字符串,有一个刷子,每次能够把一段连续的字符改为同一个字符,问你将a字符串最少改变几次变成b字符串?

思路:比较明显的区间DP,但是直接考虑两个字符串很难考虑,先考虑如果a为空串,设d[ i ][ i ] 为从第i个字符到第j个字符从空串变为b字符串的最小步数,考虑最左边的i字符,那么d[ i ][ j ] = min(d[ i + 1][ j ] ,d[i+1][ k ] + d[ k+1 ][ j ] (if b[ i ] == b[ k ]))。之后,再来考虑本来的a字符串,设ans[ i ] 表示由a变为b最少需要几步,那么ans[ i ] = min(d[ 0 ][ i ],ans[ j ] + d[ j+ 1][ i ],ans[ i - 1](if(a[ i ] == b[ i ])) )。

很好的题目,自己想不到,mark一下,学习了~~

代码如下:

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

const int MAXN = 111 ;

char str1[MAXN],str2[MAXN];

int d[MAXN][MAXN];

void dp(int l,int r)
{
    if(l==r)
    {
        d[l][r] = 1;
        return ;
    }
    d[l][r] = d[l+1][r] + 1;
    for(int i =l+1;i<=r;i++)
        if(str2[l]==str2[i])
            d[l][r] = min(d[l][r] , d[l+1][i] + d[i+1][r]);
}

int ans[MAXN];

int main()
{
    while(~scanf("%s%s",str1,str2))
    {
        memset(d,0,sizeof(d));
        int len = strlen(str1);
        for(int dis = 1;dis<=len;dis++)
        {
            for(int i = 0;i<len;i++)
            {
                int j = i+dis-1;
                if(j>=len) break;
                dp(i,j);
                //printf("d[%d][%d] = %d\n",i,j,d[i][j]);
            }
        }
        //printf("%d\n",d[0][len-1]);
        for(int i = 0;i<len;i++)
        {
            ans[i] = d[0][i];
            if(str1[i]==str2[i])
                ans[i] = min(ans[i],(i==0 ? 0: ans[i-1]));
            for(int j =0 ;j<i;j++)
                ans[i] = min(ans[i],ans[j] + d[j+1][i]);
        }
        printf("%d\n",ans[len-1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值