洛谷P2016 戰略遊戲
阿新 • • 發佈:2018-11-11
題目描述:
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])); }