zoukankan      html  css  js  c++  java
  • [SDOI2006]保安站岗

    嘟嘟嘟

    一看就是树形dp。

    刚开始我的状态dp[i][0 / 1]表示以 i 为根的子树,i 选 / 不选时的最小的经费。然后转移方程我就推不出来了,因为无法很好的表示 i 和子树的关系。比如如果 i 不选,那么 i 的子节点可以选一个也可以选多个也可以一个不选,因为 i 的儿子的儿子选了的话,i 的儿子就可以不选了。所以只用选和不选表示状态远远不够。

    根据上文的思路,先想一想会出现那些情况:

    1. i 选了,那么 i 的儿子们就随便。

    2. i 没选,但是 i 的儿子中有的选了,也就是说 i 也被控制了。

    3. i 没被控制。

    那么状态就是dp[i][0 /1 /2]分别表示:

    0:i 没被控制

    1:i 被他爹或某个儿砸控制了

    2.自己被选了

    考虑转移,因为是自底向上dp的,所以只用考虑 i 和儿子 j 的关系:

    1.dp[i][0]:那么只有dp[j][1]可以转移,因为如果从dp[j][0]转移的话,那么 j 就永远无法控制了,不合法;从dp[j][2]转移,那么 i 一定被控制,不符合dp[i][0]。所以dp[i][0] = Σdp[j][1]

    2.dp[i][1]:则 i 至少要选一个儿子,其他儿子随便(但不能是dp[j][0],原因和上面一样),所以dp[i][1] = Σmin{dp[j][1], dp[j][2]} + dp[x][2] (x != j)

    2.dp[i][2]:那么儿子们就随便了,dp[i][2] = Σmin{dp[j][0], dp[j][1], dp[j][2]} + a[i]

    第二种转移需要点技巧才能达到O(n),具体看代码。

    初值就是当 i 为叶子的时候,dp[i][1] = INF.

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int maxn = 1505;
    21 inline ll read()
    22 {
    23   ll ans = 0;
    24   char ch = getchar(), last = ' ';
    25   while(!isdigit(ch)) last = ch, ch = getchar();
    26   while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    27   if(last == '-') ans = -ans;
    28   return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32   if(x < 0) x = -x, putchar('-');
    33   if(x >= 10) write(x / 10);
    34   putchar(x % 10 + '0');
    35 }
    36 
    37 int n, a[maxn];
    38 ll dp[maxn][3];
    39 struct Edge
    40 {
    41   int nxt, to;
    42 }e[maxn << 1];
    43 int head[maxn], ecnt = -1;
    44 void addEdge(int x, int y)
    45 {
    46   e[++ecnt] = (Edge){head[x], y};
    47   head[x] = ecnt;
    48 }
    49 
    50 void dfs(int now, int f)
    51 {
    52   ll sum = 0;
    53   for(int i = head[now]; i != -1; i = e[i].nxt)
    54     {
    55       int v = e[i].to;
    56       if(v == f) continue;
    57       dfs(v, now);
    58       dp[now][0] += dp[v][1];
    59       sum += min(dp[v][1], dp[v][2]);
    60       dp[now][2] += min(dp[v][0], min(dp[v][1], dp[v][2]));
    61     }
    62   dp[now][2] += a[now]; dp[now][1] = INF;
    63   for(int i = head[now]; i != -1; i = e[i].nxt)
    64     {
    65       int v = e[i].to;
    66       if(v == f) continue;
    67       dp[now][1] = min(dp[now][1], sum - min(dp[v][1], dp[v][2]) + dp[v][2]);
    68     }
    69 }
    70 
    71 int main()
    72 {
    73   Mem(head, -1);
    74   n = read();
    75   for(int i = 1; i <= n; ++i)
    76     {
    77       int x = read(); a[x] = read();
    78       int m = read();
    79       for(int j = 1; j <= m; ++j)
    80     {
    81       int y = read();
    82       addEdge(x, y); addEdge(y, x);
    83     }
    84     }
    85   dfs(1, 0);
    86   write(min(dp[1][1], dp[1][2])), enter;
    87   return 0;
    88 }
    View Code
  • 相关阅读:
    vscode中使用less写css样式出现红色波浪线
    vue报错error Trailing spaces not allowed no-trailing-spaces
    visual code 报错error Expected space or tab after '//' in comment spaced-comment
    笔记本电脑已经启动却黑屏
    连接MySQL报错The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    IDEA搭建基于maven的springboot工程
    eclipse 下修改Dynamic Web Modulle 的问题
    firefox(火狐)下 js中设置checkbox属性checked="checked"已有,但复选框却不显示勾选的原因
    unbtun python tab补全
    python之路:进阶篇 内置函数
  • 原文地址:https://www.cnblogs.com/mrclr/p/9898275.html
Copyright © 2011-2022 走看看