UVALive 4394 String painter

来源:互联网 发布:上海科创板交易软件 编辑:程序博客网 时间:2024/04/30 14:29

题目大意:给你两个字符串,有一个刷子,每次能够把一段连续的字符改为同一个字符,问你将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;}


原创粉丝点击