zoukankan      html  css  js  c++  java
  • [JLOI 2015]战争调度

    Description

    题库链接

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

    (1leq nleq 10)

    Solution

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

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

    根据主定理,复杂度是 (O(ncdot 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
    ", ans);
        return 0;
    }
  • 相关阅读:
    学习 JS 内容知识点与个人感悟【2】
    学习两天hml的感悟
    编程一星期感悟(上)
    java基础及练习题
    java基础程序代码及Scanner和Random
    java中Random和Scanner及其循环语句
    java语言及数据类型
    SQL含义+单行函数
    DTL+数据字典+序列、索引、视图
    sql plus及SQL语句
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/12307246.html
Copyright © 2011-2022 走看看