hdu1054 Strategic Game 树形DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1054

思路:树形DP,用二分匹配也能解决

定义dp[root][1],表示以root 为根结点的子树且在root放一个士兵的最优值,那么因为在root已经有士兵了,所以对其孩子来说可以放也可以不放

那么dp[root][1]+=min(dp[son][1],dp[son][0]);

dp[root][0]表示以root为根结点的子树且在root没有放士兵的最优值,那么因为在root没有士兵,所以在其孩子节点一定要放一个士兵,才能保证与其相连的边被观察到,

那么dp[root][0]+=dp[son][1];

最后的答案即为min(dp[0][1],dp[0][0]);(我是以0为整颗树的根节点的);

状态转移方程草写出来以后,实现就比较简单了吧。。

代码如下:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 using namespace std;
 6 #define MAX 1510
 7 int dp[MAX][MAX];
 8 int n;
 9 class node
10 {
11     public:
12     int to;
13     int next;
14 };
15 node edge[MAX*3];
16 int head[MAX];
17 int vis[MAX];
18 int tol;
19 void init()
20 {
21      memset(dp,0,sizeof(dp));
22      memset(head,-1,sizeof(head));
23      memset(vis,0,sizeof(vis));
24      tol=0;
25 }
26 void Build_Tree(int u,int v)
27 {
28        edge[tol].to=v;
29        edge[tol].next=head[u];
30        head[u]=tol++;
31 
32 }
33  void input()
34  {
35     int u,v,num;
36     char c;
37     for(int k=1;k<=n;k++)
38     {
39       cin>>u>>c>>c>>num>>c;  
40       for(int i=1;i<=num;i++)
41        {
42              cin>>v;                          
43             Build_Tree(u,v);
44             Build_Tree(v,u);
45        }
46     }
47 }      
48 void dfs(int root)
49 {
50     vis[root]=1;
51     for(int i=head[root];i!=-1;i=edge[i].next)
52     {
53         if(vis[edge[i].to]) continue;
54         int son=edge[i].to;
55         dfs(son);
56 
57         dp[root][0]+=dp[son][1];
58         dp[root][1]+=min(dp[son][1],dp[son][0]);
59     }
60     dp[root][1]+=1;
61 }
62 int main()
63 {
64         while(scanf("%d",&n)!=EOF)
65         {
66                 init();
67                 input();
68                 dfs(0);
69                 cout<<min(dp[0][1],dp[0][0])<<endl;
70         }
71         return 0;
72 }
View Code

 

转载于:https://www.cnblogs.com/xiaozhuyang/p/hdu1054.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值