码迷,mamicode.com
首页 > 其他好文 > 详细

[vijos1880]选课<树形dp>

时间:2017-09-01 13:37:27      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:isp   pre   转移   状态转移方程   不能   max   algo   ace   水题   

题目链接:https://www.vijos.org/p/1180

这是一道树形dp的裸题,唯一的有意思的地方就是用到了多叉树转二叉树

然后本蒟蒻写这一道水题就是因为以前知道这个知识点但是没有怎么去实现,所以就写了这一道题来练一练手

将这道题的多叉树转换成二叉树后,接着就是状态转移方程了

我们先定义数组dp[i][j]表示第i门课,还可以选j门

然后我们可以想到,第i门课我们可以不选,如果不选,就不能去找i的左儿子,但是可以找i的右儿子,即i的右儿子(兄弟)选了j门

加入选了i,那么状态来源就是i的儿子和兄弟课程一共选了j-1门(假设儿子一方选了k门,则兄弟选了j-1-k门)

然后就可以退出我们可爱的动态转移方程式了

dp[i][j]=max{dp[i.rc][j],dp[i.lc][k]+dp[i.rc][j-1-k]+i.val};

动态方程出来了,那程序也就自然而然得出来了

技术分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<queue>
 7 #define maxn 2005
 8 using namespace std;
 9 
10 struct node{
11     int lc,rc,val;
12 }e[maxn*10];
13 
14 int n,m;
15 int dp[maxn][maxn];//第i门课,已经选了j门 
16 
17 void tree(int x,int y)
18 {
19     if(dp[x][y]!=0)return;
20     if(e[x].rc!=0)tree(e[x].rc,y);//不取自己,取兄弟
21     int tmp=dp[e[x].rc][y];
22     for(int i=0;i<y;i++)//自己选了,然后还有y-1门可以选,分别给左儿子和右儿子 
23     {
24         if(e[x].lc!=0)tree(e[x].lc,i);
25         if(e[x].rc!=0)tree(e[x].rc,y-1-i);
26         tmp=max(tmp,dp[e[x].lc][i]+dp[e[x].rc][y-i-1]+e[x].val);
27     } 
28     dp[x][y]=tmp;
29 }
30 
31 int main()
32 {
33     scanf("%d%d",&n,&m);
34     for(int i=1;i<=n;i++)
35     {
36         int b,c;
37         scanf("%d%d",&b,&c);//b为i的父亲 
38         e[i].val=c;
39         e[i].rc=e[b].lc;//b的儿子是i的兄弟 
40         e[b].lc=i;//i是b的儿子 
41     }
42     tree(e[0].lc,m);
43     
44     printf("%d",dp[e[0].lc][m]);
45 }
View Code

 

[vijos1880]选课<树形dp>

标签:isp   pre   转移   状态转移方程   不能   max   algo   ace   水题   

原文地址:http://www.cnblogs.com/Danzel-Aria233/p/7462666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!