• 【SDOI2008】山贼集团


    这是一道树形dp和状压dp结合的题目,思考量和代码细节都不少。

    我们首先定义f[i][j]表示在以i为根的子树当中,建立分部的节点状压之后为j的最大收益

    那么转移是显然的,定义k为i的儿子,那么f[i][j] = max(f[k][l] + f[i][j ^ l] + val). 其中val表示其他的收益

    我们可以预处理val数组,剩下的就是细节问题了

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 inline int read() {
     4     int ret = 0, op = 1;
     5     char c = getchar();
     6     while (c < '0' || c > '9') {
     7         if (c == '-') op = -1;
     8         c = getchar();
     9     }
    10     while (c >= '0' && c <= '9') {
    11         ret = ret * 10 + c - '0';
    12         c = getchar();
    13     }
    14     return ret * op;
    15 }
    16 int n, p;
    17 struct node {
    18     int next, to; 
    19 } a[110 << 1];
    20 int head[110 << 1], num, c[110][15];
    21 int f[110][1 << 15], val[1 << 15];
    22 inline void add(int from, int to) {
    23     a[++num].next = head[from];
    24     a[num].to = to;
    25     head[from] = num;
    26 }
    27 void dfs(int now, int fa) {
    28     for (register int i = head[now]; i != -1; i = a[i].next)
    29         if (a[i].to != fa) {
    30             dfs(a[i].to, now);
    31             for (register int j = (1 << p) - 1; j; j--) {
    32                 for (register int k = j; k; k = j & (k - 1))
    33                     f[now][j] = max(f[now][j], f[now][j ^ k] + f[a[i].to][k]);
    34             }
    35         }
    36     for (register int i = (1 << p) - 1; i; i--)
    37         f[now][i] = f[now][i] + val[i];
    38 }
    39 int main() {
    40     num = -1;
    41     memset(head, -1, sizeof(head));
    42     n = read(); p = read();
    43     for (register int i = 1; i < n; ++i) {
    44         int x = read(), y = read();
    45         add(x, y);
    46         add(y, x);
    47     }
    48     for (register int i = 1; i <= n; ++i) {
    49         for (register int j = 0; j < p; ++j) {
    50             c[i][j] = read();
    51         }
    52         f[i][0] = 0;
    53         for (register int j = 1; j < (1 << p); ++j) {
    54             int xx = j & (-j);
    55             int xxx = log2(xx);
    56             f[i][j] = f[i][j ^ xx] - c[i][xxx];
    57         }
    58     }
    59     int t = read();
    60     for (register int i = 1; i <= t; ++i) {
    61         int v = read(), tot = read(), now = 0;
    62         for (register int j = 1; j <= tot; ++j) {
    63             int nn = read();
    64             now |= (1 << (nn - 1));
    65         }
    66         val[now] += v;
    67         int k = ((1 << p) - 1) ^ now;
    68         for (register int l = k; l; l = (l - 1) & k) {
    69             val[l | now] += v;
    70         }
    71     }
    72     dfs(1, 0);
    73     printf("%d
    ", f[1][(1 << p) - 1]);
    74     return 0;
    75 }
    AC Code
  • 相关阅读:
    一个喜欢研究车的80后开车人,自己的经验和感受
    35岁前务必成功的12级跳(男女通用) 转
    如何注册ocx文件
    plsql连接oracle数据库
    float过后 高度无法自适应的解决方法
    Mysql 中文中繁杂的字 插入报错的 解决方案
    power designer 教程
    表单文本框输入时提示文字消失
    diskpart分盘代码
    linux svn 中文 https://my.oschina.net/VASKS/blog/659236
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11128888.html
Copyright © 2020-2023  润新知