UVA - 1437 String painter

版权声明:转载请注明出处 https://blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81592930

链接

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

题解

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

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81592930
今日推荐