涂色「CQOI2007」

Posted ilverene

tags:

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

题意

给定一个串,要求对空串进行染色,使其成为目标串。每一次染色可以将一段连续区间染为同一种颜色,求最小次数。


思路

典型的区间dp题。

子状态(f[i][j])表示该区间最小方案数。显然单点方案数为1。

如果一个区间的左右端点相同,那么可以理解为在最开始将整个区间染色,然后复制[l+1,r]的染色方式。

如果不同的话,那么就枚举区间中的断点,统计最小值。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {

    const int N=55;
    
    int n;
    string s;
    int f[N][N];

    inline void MAIN () {
        cin>>s,n=s.length();
        memset(f,0x3f,sizeof(f));
        for (register int i=0; i<n; ++i) f[i][i]=1;
        for (register int len=2; len<=n; ++len) {
            for (register int l=0,r=len-1; r<n; ++l,++r) {
                if (s[l]==s[r]) f[l][r]=min(f[l+1][r],f[l][r-1]);
                else {
                    for (register int k=l; k<r; ++k) {
                        f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
                    }
                }
            }
        }
        write(f[0][n-1]);
    }
    
}

int main () {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    Project::MAIN();
}

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

CQOI2007 涂色

[CQOI2007]涂色

luogu P4170ybtoj 区间DP课堂过关 例题2木板涂色 & [CQOI2007]涂色

bzoj1260: [CQOI2007]涂色paint

bzoj1260 [CQOI2007]涂色paint

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