题目描述:
Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。
他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。
注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。
请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵.
题解:
一看就是树形DP题。
我们设f(x) 表示选定 x, 保证子树合法,子树内所需要的最小点数。g(x) 表示不选择 x, 保证子树合法所需要的最小点数
可以推出:
f(x) = ∑min{f(son[x]), g(son[x])}
g(x) = ∑f(son[x])
附上代码:
#include<cstdio> #define inf 1000000000 int n,a,b,c,idx,head[1501],f[1501][2]; struct Edge { int to,next; }edge[3001]; int min(int x,int y) { if(x<y) return x; return y; } void addedge(int x,int y) { ++idx; edge[idx].to=y; edge[idx].next=head[x]; head[x]=idx; } void dfs(int x,int from) { f[x][1]=1; f[x][0]=0; if(head[x]==0) f[x][0]=inf; for(int i=head[x];i;i=edge[i].next) { if(edge[i].to!=from) { dfs(edge[i].to,x); f[x][1]+=min(f[edge[i].to][1],f[edge[i].to][0]); f[x][0]+=f[edge[i].to][1]; } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b);a++; for(int j=1;j<=b;j++) { scanf("%d",&c);c++; addedge(a,c); addedge(c,a); } } dfs(1,0); printf("%d",min(f[1][1],f[1][0])); }