$loj10156/$洛谷$2016$ 战略游戏 树形$DP$

洛谷loj

 

Desription

Bob 喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的方法。现在他有个问题。

现在他有座古城堡,古城堡的路形成一棵树。他要在这棵树的节点上放置最少数目的士兵,使得这些士兵能够瞭望到所有的路。

注意:某个士兵在一个节点上时,与该节点相连的所有边都将能被瞭望到。

请你编一个程序,给定一棵树,帮 Bob 计算出他最少要放置的士兵数。

 

Sol

状态:

f[i][0]表示i不放士兵时,以i为根的子树所需要的最小士兵数

f[i][1]表示i放士兵时,以i为根的子树所需要的最小士兵数

转移:

f[i][0]:i不放,那么它的子结点都要放

f[i][1]:i放,那么它的子结点可放可不放,取小即可

 

感觉比较板子题QwQ

 

Code

(It was written long long ago.)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 using namespace std;
 5 int r()
 6 {
 7     int x=0,y=1;;char ch;
 8     ch=getchar();
 9     while(ch<'0'||ch>'9') {if(ch=='-') y=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}  
11     return x*y;
12 }
13 int n;
14 int num[1600];
15 bool ff[1600];
16 vector<int> son[1600];
17 int root;
18 void read()
19 {
20     n=r();
21     for(int i=0;i<n;i++)
22     {
23         i=r();
24         num[i]=r();
25         for(int j=1;j<=num[i];j++)
26         {
27             int x=r();
28             son[i].push_back(x);
29             ff[x]=1;
30         }
31     }
32     while(ff[root]) root++;
33 }
34 int f[1600][2];
35 void dp(int x)
36 {
37     f[x][0]=0;
38     f[x][1]=1;
39     if(num[x]==0) return ;
40     for(int i=0;i<num[x];i++)
41     {
42         int y=son[x][i];dp(y);
43         f[x][0]+=f[y][1];
44         f[x][1]+=min(f[y][1],f[y][0]);
45     }
46 }
47 int main()
48 {
49     read();
50     dp(root);
51     int ans=min(f[root][0],f[root][1]);
52     printf("%d",ans);
53     return 0;
54 }
View Code

 

posted @ 2019-06-12 11:13  DTTTTTTT  阅读(216)  评论(0编辑  收藏  举报