皇宫看守(树形dp)

皇宫看守(树形dp)

 

 

 

 

 

 题解:

不同于战略游戏那道题要求每边有人看守,即只能靠自己或者靠儿子,本题要求每个点有人看守,即对于点root可以靠自己靠儿子或靠父亲

设dp[root][0/1/2]表示0靠自己1靠爸爸2靠儿子

root靠自己可以从儿子的三种状态转移,但是要加上自己设看守的费用

root靠爸爸可以让儿子靠自己或者靠儿子的儿子(好爸爸)

注意这里!root靠儿子必须要有一个儿子靠自己,其余儿子靠自己或者靠儿子的儿子,实现见代码

特别的,根结点不能靠爸爸,叶子结点不能靠儿子

AC_Code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1500+10;
 5 const int mod = 1e9+7;
 6 const int inf = 0x3f3f3f3f;
 7 
 8 int cnt[maxn],dp[maxn][3], son[maxn][maxn], k[maxn],fa[maxn];
 9 int n,x;
10 
11 //dp[i][0]:靠自己可以看守到i所需的最小花费
12 //dp[i][1]:靠爸爸可以看守到i所需的最小花费
13 //dp[i][2]:靠儿子可以看守到i所需的最小花费
14 
15 void dfs(int root){
16     if( !cnt[root] ){           //叶子节点
17         dp[root][0] = k[root];
18         dp[root][1] = 0;
19         dp[root][2] = inf;
20         return ;
21     }
22 
23     for(int i=1;i<=cnt[root];i++){
24         dfs( son[root][i] );
25     }
26     dp[root][0] = k[root];
27     int f = 0;
28     for(int i=1;i<=cnt[root];i++){
29         dp[root][0] += min(dp[son[root][i]][1], min(dp[son[root][i]][0], dp[son[root][i]][2]));
30         dp[root][1] += min(dp[son[root][i]][0], dp[son[root][i]][2]);
31         dp[root][2] += min(dp[son[root][i]][0], dp[son[root][i]][2]);
32 
33         if( dp[son[root][i]][0]<=dp[son[root][i]][2] ){//标记有没有哪个儿子靠自己比靠儿子的花费少的
34             f = 1;
35         }
36     }
37     if( !f ){//若没有
38         int minn = 0x3f3f3f3f;
39         for(int i=1;i<=cnt[root];i++){
40             minn = min(minn, dp[son[root][i]][0]-dp[son[root][i]][2]);
41         }
42         dp[root][2] += minn;
43     }
44 }
45 
46 int main()
47 {
48     memset(dp,0,sizeof(dp));
49     scanf("%d",&n);
50     for(int i=1;i<=n;i++){
51         int x; scanf("%d",&x);
52         scanf("%d%d",&k[x],&cnt[x]);
53         for(int j=1;j<=cnt[x];j++){
54             scanf("%d",&son[x][j]);
55             fa[son[x][j]] = x;
56         }
57     }
58     for(int i=1;i<=n;i++){
59         if( !fa[i] ){
60             dfs(i);
61             int ans = min(dp[i][0], dp[i][2]);
62             printf("%d\n",ans);
63             break;
64         }
65     }
66     return 0;
67 }

 参考博客:here

posted @ 2020-12-02 20:00  swsyya  阅读(325)  评论(0编辑  收藏  举报

回到顶部