P4170 [CQOI2007]涂色

Posted hexqwq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4170 [CQOI2007]涂色相关的知识,希望对你有一定的参考价值。

戳这里

  • 先看一下题意:

    ? 给你一个 n 长度的木板,刚开始是没有颜色的,现在你需要用最少的涂色次数,让这个木板的颜色变成给定的目标颜色

  • 解析

    1. 读懂题意,发现这是一个求处理一个区间的最小操作数的题目,这时候就要考虑能不能用区间DP处理这个题目,一般来说,区间DP的时间复杂度为 (n^3)(n^2),本题 n 最大仅 50 ,在时间复杂度上满足要求。

    2. 在确定题目是区间DP后,我们要思考这个题的 状态转移方程

      • 定义(f[i][j]) 为 处理好区间 i 至 j 涂色的最小次数

      • 先考虑区间长度为 1 的情况,如果木板的长度只有 1,那么涂色次数很显然就是 1。

      • 在考虑一下区间长度为 2 时

        首先,如果两端的颜色一样,那么我们只需要一次涂色,就能把这个区间染成需要的颜色

        如果,两端的颜色不一样,那么染色的次数就应该时 2 了

      • 当区间长度更大时,会怎么样呢

        假设我们当前要计算的区间为 (f[i][j])

        如果,(s[i] == s[j]) ,那么,我们可以第一笔就涂满整个区间,所以,此时的状态可以由 (f[i+1][j])(f[i][j-1]) 中较小的转移,即
        [ f[i][j] = min(f[i+1][j],f[i][j-1]) ]
        那如果,(s[i] != s[j]),我们就只能枚举断点来找到最优的方案,即
        [ f[i][j] = min(f[i][j],f[i][k]+f[k+1][j]) ]

    3. 以上就是本题的解释。在写区间DP的时候,感觉难的主要就是区间和合并问题,还有就是一些特殊的优化 (四边形不等式)

  • 放代码QwQ

#include<bits/stdc++.h>

using namespace std;

const int Inf = 0x7f7f7f7f;

int dp[233][233];
char s[233];

int main(){
    scanf("%s",s+1);
    int Len = strlen(s+1);
    for(int i=1;i<=Len;i++)
        dp[i][i] = 1;
    for(int len = 2;len <= Len;len++)
    {
        for(int l=1;l+len-1<=Len;l++)
        {
            int r = l + len - 1;
            dp[l][r] = Inf;
            if( s[l] == s[r] )  dp[l][r] = min(dp[l+1][r],dp[l][r-1]);
            else 
                for(int k=l;k<r;k++)
                    dp[l][r] = min(dp[l][r],dp[l][k] + dp[k+1][r]);
        }
    }
    printf("%d",dp[1][Len]);
    return 0;
}

以上是关于P4170 [CQOI2007]涂色的主要内容,如果未能解决你的问题,请参考以下文章

P4170 [CQOI2007]涂色

解题报告:luogu P4170

解题报告:luogu P4170

BZOJ1260 [CQOI2007]涂色paint(区间dp)

涂色「CQOI2007」

CQOI2007 涂色