UVA - 1437 String painter

链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4183

题解

贪心和 dp d p 相结合
s s 刷到t不好想,我们先想怎么从空序列刷到 t t
g[i][j]表示从空序列(可以理解为一开始全是*)刷出 t t 序列的最小花费
t[i]=t[j]时,我如果把 [i,j] [ i , j ] 全刷成 t[i] t [ i ] 然后再接着刷,这样肯定最优,因为如果我不这样刷,而是先把中间刷好,再刷两头,中间的费用不会更优,刷两端的费用肯定会 +1 + 1 。此时 g[i][j]=g[i][j1] g [ i ] [ j ] = g [ i ] [ j − 1 ] ,这样转移的正确性在于,我可以构造一种把 i,j1 i , j − 1 先全刷成 t[i] t [ i ] ,再接着刷的方案,这个方案和上述所说的是等价的
现在求出了 g[][] g [ ] [ ]
我令 f[i] f [ i ] 表示 s s 的前i个字母刷成 t t 的前i个字母的最小花费
s[i]=t[i] s [ i ] = t [ i ] 时, f[i]=f[i1] f [ i ] = f [ i − 1 ]
s[i]t[i] s [ i ] ≠ t [ i ] 时, f[i]=min{f[k]+g[k+1][j]} f [ i ] = m i n { f [ k ] + g [ k + 1 ] [ j ] }

思路总结

这个题学会的新思路有:

  • 把一个题拆成两个步骤,分步完成使思维复杂度降低
  • 对于区间类型的题目,可以强制分成若干个不相邻的段进行转移

代码

//DP
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cmath>
#define maxn 200
#define inf 0x3f3f3f3f
#define cl(x,y) memset(x,y,sizeof(x))
using namespace std;
int g[maxn][maxn], f[maxn];
char s[maxn], t[maxn], n;
void init()
{
    n=strlen(s+1);
    cl(g,inf), cl(f,inf);
}
void dp()
{
    int i, j, l, k;
    for(i=1;i<=n;i++)g[i][i]=1;
    for(l=2;l<=n;l++)for(i=1;i+l-1<=n;i++)
    {
        j=i+l-1;
        if(t[i]==t[j])g[i][j]=g[i][j-1];
        else for(k=i;k<j;k++)g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]);
    }
    f[0]=0;
    for(i=1;i<=n;i++)
    {
        if(s[i]==t[i])f[i]=f[i-1];
        else for(j=0;j<i;j++)f[i]=min(f[i],f[j]+g[j+1][i]);
    }
    printf("%d\n",f[n]);
}
int main()
{
    while(~scanf("%s%s",s+1,t+1))init(), dp();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值