码迷,mamicode.com
首页 > 其他好文 > 详细

[JLOI 2015]战争调度

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

标签:text   复杂度   space   pre   bit   max   并且   特定   不能   

Description

题库链接

给你一棵 \(n\) 层的满二叉树,每个节点可选择为黑或者白。所有的叶子节点都会产生一定的贡献值,具体地,它与其祖先选色相同时会有特定的值(输入给定)。问如何染色使得所有贡献和最大。并且规定染成黑色的叶子节点不能超过 \(m\) 个。

\(1\leq n\leq 10\)

Solution

容易发现一个节点的贡献只与其 \(n-1\) 个祖先有关。我们可以枚举祖先节点的状态进而得到每个叶子的贡献。

然后对于不能超过 \(m\) 个的限制,我们可以记 \(f_{i,j}\) 表示节点 \(i\) 的子树中选出了 \(j\) 个黑点,树形 \(\text{DP}\) 解决。

根据主定理,复杂度是 \(O(n\cdot 2^{2n})\)

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1024+5;

int n, m;
int f[N][N], v[N], w[N][10], a[N][10];

void dfs(int u, int k) {
    for (int i = 0; i <= (1<<k); i++)
        f[u][i] = 0;
    if (!k) {
        for (int i = 1, t = u; i < n; i++)
            f[u][1] += v[t /= 2]*w[u-(1<<n-1)+1][i];
        for (int i = 1, t = u; i < n; i++)
            f[u][0] += (!v[t /= 2])*a[u-(1<<n-1)+1][i];
    } else for (int qwq = 0; qwq <= 1; qwq++) {
        v[u] = qwq;
        dfs(u<<1, k-1), dfs(u<<1|1, k-1);
        for (int i = 0; i <= (1<<k); i++)
            for (int j = max(0, i-(1<<k-1)); j <= min((1<<k-1), i); j++)
                f[u][i] = max(f[u][i], f[u<<1][j]+f[u<<1|1][i-j]);
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= (1<<n-1); i++)
        for (int j = 1; j < n; j++)
            scanf("%d", &w[i][j]);
    for (int i = 1; i <= (1<<n-1); i++)
        for (int j = 1; j < n; j++)
            scanf("%d", &a[i][j]);
    dfs(1, n-1);
    int ans = 0;
    for (int i = 0; i <= m; i++) ans = max(ans, f[1][i]);
    printf("%d\n", ans);
    return 0;
}

[JLOI 2015]战争调度

标签:text   复杂度   space   pre   bit   max   并且   特定   不能   

原文地址:https://www.cnblogs.com/NaVi-Awson/p/12307246.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!