• [UVA1437] String painter


    题目链接

    题意

      有两个由小写英文字母组成的等长字符串A和B。你可以一次性将一个字符串的一个子串中的字符全部刷成任何你想要同一字符。求把字符串A刷成B的最少次数。

    分析

      这一题非常像 [CQOI2007] 涂色 ,准确说是加强版

      但是简单考虑直接将A刷成B,由于AB两串中字符的不确定性(有些位置上字符相同而有些不同),状态转移方程比较难推出,所以可以换一种思路来简化问题

      我们可以分两步DP处理,先求出将空白串刷成B串中任意子串的次数,再借此得出A刷成B的结果

      定义二维数组f[i][j]表示将空白串的i到j位置刷成B串的i到j位置的最少次数

      当 $i=j$ 时,$f[i][j]=1$

      当 $i eq j$ 时,

    $$
    {large f[i][j]=
    egin{cases}
    min(f[i+1][j],f[i][j-1]) & {B[i]=B[j]} \
    min(f[i][j],f[i][k]+f[k+1][j])(i leq k < j) & {B[i] eq B[j]}
    end{cases}}
    $$

      显然需要区间DP,不断扩展枚举子串的长度,并且要枚举子串中间断点k

      然后定义d[i]表示将A串前i个字符刷成B串前i个字符的最少次数,最初 $d[i]=f[1][i]$

    $$
    {large d[i]=
    egin{cases}
    min(d[i],d[i-1]) & {A[i]=B[j]} \
    min(d[i],d[k]+f[k+1][i])(i leq k < j) & {A[i] eq B[j]}
    end{cases}}
    $$

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    using namespace std;
    #define ll long long
    #define inf 0x7fffffff
    #define N 105
    
    int n;
    char a[N], b[N];
    int f[N][N], d[N];
    
    int main() {
        while (scanf("%s%s", a + 1, b + 1) == 2) {
            memset(f, 0x3f, sizeof f);
            n = strlen(a + 1);
            for (int i = 1; i <= n; i++) f[i][i] = 1;
            for (int l = 2; l <= n; l++)
                for (int i = 1; i + l - 1 <= n; i++) {
                    int j = i + l - 1;
                    if (b[i] == b[j])
                        f[i][j] = min(f[i + 1][j], f[i][j - 1]);
                    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++) {
                d[i] = f[1][i];
                if (a[i] == b[i])
                    d[i] = min(d[i], d[i - 1]);
                else for (int k = 1; k < i; k++)
                    d[i] = min(d[i], d[k] + f[k + 1][i]);
            }
            printf("%d
    ", d[n]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    使用迭代器模式批量获得数据(C#实现)
    如何从技术上预防抢票软件刷屏
    如何用Tesseract做日文OCR(c#实现)
    我的.net开发百宝箱
    程序员必备基础:Git 命令全方位学习
    Java 异常处理的十个建议
    50道Java集合经典面试题(收藏版)
    记一次接口性能优化实践总结:优化接口性能的八个建议
    100道MySQL数据库经典面试题解析(收藏版)
    800+Java后端经典面试题,希望你找到自己理想的Offer呀~
  • 原文地址:https://www.cnblogs.com/Pedesis/p/10963226.html
Copyright © 2020-2023  润新知