• 4557: [JLoi2016]侦察守卫 树形dp


    一道好题,但也是一道水题。 可怜yyl蒟蒻看了别人怎么开数组后还是不会写。 orz各位大神。

    接下来上大神的题解(注意不是我的):

    比较简单的一个DP
    f[i][j]表示节点为i的子树向下j层以下需要被覆盖的节点已经被覆盖了的答案
    g[i][j]表示节点为i的子树,子树内需要被覆盖的几点已经被覆盖了,还可以向上覆盖j层的答案
    f[i][0]=g[i][0]
    然后正着反着取两遍最小值即可

    接着yy应该可以出来了。感觉不难。就是想不到……………………。too young too simple

     1 #include<cstdio>
     2 #include<iostream>
     3 #define rep(i,j,k) for(register int i = j; i <= k; i++)
     4 #define dow(i,j,k) for(register int i = j; i >= k; i--)
     5 #define ez(i,j) for(edge*i = head[j]; i; i=i->next)
     6 #define maxn 502333
     7 #define inf 0x7fffffff
     8 using namespace std;
     9  
    10 inline int read() {
    11     int s = 0, t =1; char c = getchar();
    12     while( !isdigit(c) ) { if( c == '-' ) t = -1; c = getchar(); }
    13     while( isdigit(c) ) s = s * 10 + c - 48, c = getchar();
    14     return s * t;
    15 }
    16  
    17 struct edge{ int to; edge*next; } e[maxn<<1], *pt = e, *head[maxn];
    18 inline void add(int x,int y) { pt->to = y, pt->next = head[x], head[x] = pt++; pt->to = x, pt->next = head[y], head[y] = pt++; }
    19 int f[maxn][25], g[maxn][25], w[maxn], d; bool ned[maxn][25];
    20  
    21 #define to i->to
    22 inline void dp(int x,int fa) {
    23     bool out = 0;
    24     ez(i,x) if( to != fa ) { dp(to,x), out = 1; }
    25     rep(j,1,d) {
    26         ned[x][j] |= ned[x][j-1];
    27         if( !ned[x][j] ) ez(i,x) if( to != fa && ned[to][j-1] ) { ned[x][j] |= 1; break; }
    28     }
    29     if( !out ) {
    30         rep(i,1,d) g[x][i] = w[x];
    31         if( ned[x][0] ) f[x][0] = g[x][0] = w[x]; else f[x][0] = g[x][0] = 0;
    32         rep(i,1,d) f[x][i] = 0;
    33         return;
    34     }
    35     rep(j,1,d) {
    36         f[x][j] = 0;
    37         ez(i,x) if( to != fa ) f[x][j] += f[to][j-1]; 
    38     }
    39     g[x][d] = 0;
    40     ez(i,x) if( to != fa ) g[x][d] += f[to][d];
    41     g[x][d] += w[x];
    42     dow(j,d-1,0) {
    43         int sum = 0;
    44         ez(i,x) if( to != fa ) sum += f[to][j];
    45         g[x][j] = inf;
    46         ez(i,x) if( to != fa ) g[x][j] = min(g[x][j],g[to][j+1]+sum-f[to][j]);
    47     }
    48     dow(i,d,1) g[x][i-1] = min(g[x][i-1],g[x][i]);
    49     f[x][0] = g[x][0];
    50     rep(i,1,d) f[x][i] = min(f[x][i],f[x][i-1]);
    51     dow(i,d-1,0) if( !ned[x][i] ) f[x][i] = min(f[x][i+1], f[x][i]);
    52     g[x][0] = f[x][0];
    53 }
    54  
    55 int main() {
    56     int n = read(); d = read();
    57     rep(i,1,n) w[i] = read(); 
    58     int m = read();
    59     rep(i,1,m) ned[read()][0] = 1;
    60     rep(i,1,n-1) add(read(),read());
    61     dp(1,0);
    62     printf("%d
    ", f[1][0]);
    63     return 0;
    64 }
  • 相关阅读:
    《软件需求模式》阅读笔记二
    《软件需求模式》阅读笔记一
    《编写有效用例》阅读笔记三
    《编写有效用例》阅读笔记二
    《编写有效用例》阅读笔记一
    《软件需求十步走》阅读笔记三
    英文一分钟自我介绍
    c语言面试常见题
    docker
    LLDP
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5463397.html
Copyright © 2020-2023  润新知