P4170 [CQOI2007]涂色 题解

link
由数据范围易知,本题为区间 DP。
设状态 fi,j 表示 i ~ j 区间完成涂色时所需的最少的涂色次数
则有转移方程:fi,j=max{fi,k+fk+1,j}(k[i,j)) 初值:i[1,n]fi,i=1(区间长度为 1 时显然最少涂色次数为 1) 目标:f1,n
上区间 DP 模板

#include <bits/stdc++.h>
using namespace std;


//    0. Enough array size? Enough array size? Enough array size? Integer overflow?

//    1. Think TWICE, Code ONCE!
//    Are there any counterexamples to your algo?

//    2. Be careful about the BOUNDARIES!
//    N=1? P=1? Something about 0?

//    3. Do not make STUPID MISTAKES!
//    Time complexity? Memory usage? Precision error?


#define debug(args...) fprintf(stderr, ##args)
#define gc getchar
using ll = long long;

const ll inf = 1e18;
const int N = 57;

int n, f[N][N];
char s[N];

int main() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    memset(f, 0x3f, sizeof f);
    for (int i = 1; i <= n; ++i) f[i][i] = 1;
    for (int len = 1; len < n; ++len)
        for (int l = 1, r = l + len; r <= n; ++l, ++r)
            for (int k = l; k < r; ++k) f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);

    printf("%d", f[1][n]);

    return 0;
}

结果
显然,我们刚才没有考虑特殊情况

特殊情况

易知当输入的字符串转移时若 sl == sr 为特殊情况,我们需要特判这种情况。
此时便不必对 l,r 区间染色。选择对区间 l,r1 染色,或对区间 l+1,r 染色,两者中取次小值即可。
状态转移方程变为:fi,j=min{fi,j1,fi+1,j}(si=sj)
至此,本题就可以正常的通过了
code

#include <bits/stdc++.h>
using namespace std;


//    0. Enough array size? Enough array size? Enough array size? Integer overflow?

//    1. Think TWICE, Code ONCE!
//    Are there any counterexamples to your algo?

//    2. Be careful about the BOUNDARIES!
//    N=1? P=1? Something about 0?

//    3. Do not make STUPID MISTAKES!
//    Time complexity? Memory usage? Precision error?


#define debug(args...) fprintf(stderr, ##args)
#define gc getchar
using ll = long long;

const ll inf = 1e18;
const int N = 57;

int n, f[N][N];
char s[N];

int main() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    memset(f, 0x3f, sizeof f);
    for (int i = 1; i <= n; ++i) f[i][i] = 1;
    for (int len = 1; len < n; ++len)
        for (int l = 1, r = l + len; r <= n; ++l, ++r)
            if (s[l] == s[r]) f[l][r] = min(f[l][r - 1], f[l + 1][r]);
            else for (int k = l; k < r; ++k) f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);
    printf("%d", f[1][n]);
    return 0;
}

AC

posted @   CKB2008  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示