1. 程式人生 > >洛谷P2016 戰略遊戲

洛谷P2016 戰略遊戲

題目描述:

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])); }