P1122战略游戏 & P2016最大子树和 树形DP

裸的树形DP

P2016   战略游戏

对于(u,v)这条边,吾们在树上进行DP;

可以分两种情况讨论:

  1. 对于指向儿子的u,它选择不放放哨的,此时这条边要被看见必须在v放置。

      状态转移:dp[u][0]+=dp[v][1];

      2.放哨的弟弟已经在u啦,但不知道把放哨的再放在v上是不是更优的。

      状态转移:dp[u][1]+=min(dp[v][0],dp[v][1]);

对于每棵树更新一下,递归实现即可。(包括原树与子树)

情况2的不确定v如图:

此时(如果以u为节点的话)最优解为(u,v);

 

这道题的代码实现:

 1 #include<bits/stdc++.h>//动规 
 2 using namespace std;
 3 struct edge{
 4     int nxt,to;
 5 }ea[3010];
 6 int n,cnt,head[3010],dp[3010][2];
 7 void add_edge(int u,int v){ 
 8     ea[++cnt].to=v,ea[cnt].nxt=head[u],head[u]=cnt;
 9     ea[++cnt].to=u,ea[cnt].nxt=head[v],head[v]=cnt;
10 }
11 void dfs(int u,int fa){
12     dp[u][1]=1,dp[u][0]=0;
13     for(int i=head[u];i;i=ea[i].nxt){
14         int v=ea[i].to;
15         if(v==fa) continue;
16         dfs(v,u);
17         dp[u][0]+=dp[v][1];
18         dp[u][1]+=min(dp[v][0],dp[v][1]);
19     }
20 }
21 int main(){
22     cin>>n;
23     for(int i=1,u,num;i<=n;i++){
24         cin>>u>>num;
25         for(int i=1,v;i<=num;i++){
26             cin>>v;
27             add_edge(u,v);
28         }
29     }
30     dfs(0,0);
31     cout<<min(dp[0][0],dp[0][1]);
32 } 
View Code

 

P1122  最大紫薯

 这道题贪心很明显是对的,(因为局部最优解一定会影响到整体)但我是来说DP的……

  设置状态dp[u]表示以u为根节点的子树的权值最大值。

    递归更新的正确性同贪心思路。(如果此子树可删并且由叶子往根扫,不需要质疑它的正确性)

      转移方程(话说跟数字三角形有异曲同工之妙)为:dp[u]=max(0,dp[v]);

同理分析,对于此图

 

递归从叶子扫,把4号点删去,3,5点删去。

代码如下:

 1 #include<bits/stdc++.h>//动规 
 2 using namespace std;
 3 struct edge{
 4     int nxt,to;
 5 }ea[35002];
 6 int n,cnt,head[35002],dp[35002],val[35002],ans=-2147483647;
 7 void add_edge(int u,int v){
 8     ea[++cnt].to=v,ea[cnt].nxt=head[u],head[u]=cnt;
 9     ea[++cnt].to=u,ea[cnt].nxt=head[v],head[v]=cnt;
10 }
11 void dfs(int u,int fa){
12     dp[u]=val[u];
13     for(int i=head[u];i;i=ea[i].nxt){
14         int v=ea[i].to;
15         if(v==fa) continue;
16         dfs(v,u);
17         dp[u]+=max(0,dp[v]);    
18     }
19     ans=max(ans,dp[u]);
20 }
21 int main(){
22     cin>>n;
23     for(int i=1;i<=n;i++) cin>>val[i];
24     for(int i=1,u,v;i<n;i++){
25         cin>>u>>v;
26         add_edge(u,v);
27     }
28     dfs(1,0);
29     cout<<ans;
30 }
View Code

 

posted @ 2019-07-28 10:02  admire◢◤  阅读(146)  评论(0编辑  收藏  举报