POJ1463-Strategic game-(树形dp)

http://poj.org/problem?id=1463

题意:有一棵n个结点的树,要在这棵树上放士兵守卫,一个士兵可以守卫自己所在的位置以及与之相邻的点。问最少放多少个士兵?

题解:对于每个点,两种情况,放与不放,放则计数1,不放则计数0。

对于某个点x

如果不放,则与他相邻的点必然要放,否则谁来守卫点x?

如果放,则与他相邻的点可放可不放。

首先要造一棵树,从根节点对所有儿子节点深搜。

dp[i][0]和dp[i][1]表示 包括i本身 和 以i为父节点的子孙结点的摆放数 的累计最小值。

对于样例1,可以造出如下这样的树,0是根结点,指向儿子。

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<math.h>
 6 #include<string>
 7 #include<map>
 8 #include<queue>
 9 #include<stack>
10 #include<set>
11 #define ll long long
12 #define inf 0x3f3f3f3f
13 using namespace std;
14 
15 int n,m;
16 int dp[10086][2];
17 vector<int>son[10086];
18 bool vis[10086];
19 
20 void dfs(int x)
21 {
22     dp[x][0]=0;
23     dp[x][1]=1;///每次进入深搜,初始化这个点是可以选或者不选
24     for(int i=0;i<son[x].size();i++)
25     {
26         int y=son[x][i];
27         dfs(y);
28         dp[x][0]+=dp[y][1]; ///如果不选,那么谁来守卫?那儿子就需要守卫
29         dp[x][1]+=min(dp[y][0],dp[y][1]);///如果选择守卫,则儿子可以选择守卫或者不守卫
30     }
31 }
32 
33 int main()
34 {
35     while(scanf("%d",&n)!=EOF)
36     {
37         for(int i=0;i<n;i++)
38             son[i].clear();
39         memset(vis,false,sizeof(vis));
40         memset(dp,0,sizeof(dp));
41         for(int i=0;i<n;i++)
42         {
43             int x,y;
44             scanf("%d:(%d)",&x,&m);
45             while(m--)
46             {
47                 scanf("%d",&y);
48                 son[x].push_back(y);
49                 vis[y]=true;///y有父亲,不能作为根结点
50             }
51         }
52         for(int i=0;i<n;i++)
53         {
54             if(!vis[i])///找到没有儿子的结点作为根节点
55             {
56                 dfs(i);
57                 printf("%d\n",min(dp[i][0],dp[i][1]));///取根节点的最小情况
58                 break;
59             }
60         }
61     }
62     return 0;
63 }
/**
dfs(0)
{
    dp[0][0]=0;dp[0][1]=1;
    for(int i=0;i<1;i++)
    {
        y=1;
        dfs(1)
        {
            dp[1][0]=0;dp[1][1]=1;
            for(int i=0;i<2;i++)
            {
                now i=0;
                y=2;
                dfs(2);
                {
                    dp[2][0]=0;dp[2][1]=1;
                }
                dp[1][0]=dp[1][0]+dp[2][1]=0+1=1;
                dp[1][1]+=min(dp[2][0],dp[2][1])=1+0=1;

                now i=1;

                y=3;
                dfs(3);
                {
                    dp[3][0]=0;dp[3][1]=1;
                }
                dp[1][0]=dp[1][0]+dp[3][1]=1+1=2;
                dp[1][1]+=min(dp[3][0],dp[3][1])=1+0=1;
            }
            dp[0][0]=dp[0][0]+dp[1][1]=0+1=1;
            dp[0][1]+=min(dp[1][0],dp[1][1])=1+1=2;

        }
    }

}
*/
模拟样例1的深搜过程

猜你喜欢

转载自www.cnblogs.com/shoulinniao/p/11392154.html