首页 > 其他 > 详细

「CF1286A」Garland

时间:2020-06-14 17:13:56      阅读:33      评论:0      收藏:0      [点我收藏+]

传送门

考虑 \(\text{DP}\),设 \(dp_{i, j, k, 0 / 1}\) 表示 \(dp\) 完前 \(i\) 位,补了 \(j\) 个偶数,\(k\) 个奇数,第 \(i\) 个位置填的是偶/奇(\(0/1\))的最小答案。

具体怎么转移看代码就好了,浅显易懂(((

参考代码:

#include <cstring>
#include <cstdio>

const int _ = 102;

int n, a[_], cnt[2], dp[_][_][_][2];

int min(int a, int b) { return a < b ? a : b; }

void chkmin(int& a, int b) { a = min(a, b); }

int main() {
#ifndef ONLINE_JUDGE
    freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
#endif
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    cnt[0] = n / 2, cnt[1] = (n + 1) / 2;
    for (int i = 1; i <= n; ++i)
        if (a[i] == 0) a[i] = -1; else --cnt[a[i] &= 1];
    memset(dp, 0x3f, sizeof dp);
    if (a[1] != -1)
        dp[1][cnt[0]][cnt[1]][a[1]] = 0;
    else {
        if (cnt[0] > 0) dp[1][cnt[0] - 1][cnt[1]][0] = 0;
        if (cnt[1] > 0) dp[1][cnt[0]][cnt[1] - 1][1] = 0;
    }
    for (int i = 2; i <= n; ++i) {
        if (a[i] != -1) {
            for (int j = 0; j <= cnt[0]; ++j)
                for (int k = 0; k <= cnt[1]; ++k) {
                    chkmin(dp[i][j][k][a[i]], dp[i - 1][j][k][0] + (a[i] != 0));
                    chkmin(dp[i][j][k][a[i]], dp[i - 1][j][k][1] + (a[i] != 1));
                }
        } else {
            for (int j = 0; j <= cnt[0]; ++j)
                for (int k = 0; k <= cnt[1]; ++k) {
                    chkmin(dp[i][j][k][0], dp[i - 1][j + 1][k][0]);
                    chkmin(dp[i][j][k][0], dp[i - 1][j + 1][k][1] + 1);
                    chkmin(dp[i][j][k][1], dp[i - 1][j][k + 1][1]);
                    chkmin(dp[i][j][k][1], dp[i - 1][j][k + 1][0] + 1);
                }
        }
    }
    printf("%d\n", min(dp[n][0][0][0], dp[n][0][0][1]));
    return 0;
}

「CF1286A」Garland

原文:https://www.cnblogs.com/zsbzsb/p/13125251.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!