[codevs1378]选课

题目

做这道题本来是想复习一下最基本的树形dp模型,结果没想到卡了大半天还调不出来

首先是把多叉树转化为二叉树

Ans(x,y):表示节点x取y门课的最高学分

Ans(x,y)=max(Ans(x.l,k-1)+x.v+f(x.r,y-k))k=0,1,..y

400表示空节点,0是根节点.

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 struct node{
 7     int l,r,value;
 8 }T[600]={0};
 9 int n,m;
10 int Ans[600][600];
11 int f[350]={0};//记录是否有左孩子,若有则记录左孩子的编号 
12 int read(){
13     char ch=getchar();
14     int x=0,f=1;
15     while (ch<'0'||ch>'9'){
16         if (ch=='-') f=-1;
17         ch=getchar();
18     }
19     while (ch>='0'&&ch<='9'){
20         x=x*10+ch-'0';
21         ch=getchar();        
22     }
23     return x*f;
24 }
25 int Tree_Solve(int fa,int num){
26     if (Ans[fa][num]>=0) return (Ans[fa][num]);
27     int cnt=Tree_Solve(T[fa].r,num);//全部取右孩子
28     for (int k=0;k<num;k++)
29         cnt=max(cnt,Tree_Solve(T[fa].l,k)+Tree_Solve(T[fa].r,num-k-1)+T[fa].value);
30     Ans[fa][num]=cnt; 
31     return cnt;
32 }
33 int main(){
34     freopen("input.in","r",stdin);
35     freopen("output.out","w",stdout);
36     n=read(),m=read();
37     memset(f,0,sizeof(f));
38     for (int i=0;i<=n;i++)
39       T[i].l=T[i].r=400;//边界 
40     //读入并建树(多叉树转化为二叉树) 
41     for (int i=1;i<=n;i++){
42         int a=read(),b=read();
43         T[i].value=b;
44         if (!f[a]) T[a].l=i;
45          else T[f[a]].r=i;//相当于一条链 
46         f[a]=i;
47     }
48     //DP:memoried search
49     memset(Ans,-1,sizeof(Ans));
50     for (int i=0;i<=n;i++)//边界一定要考虑详细 
51       Ans[i][0]=0,Ans[400][i]=0;
52     printf("%d",Tree_Solve(T[0].l,m));
53     return 0;
54 }
View Code

 

posted @ 2017-04-27 11:10  Vincent_hwh  阅读(144)  评论(0编辑  收藏  举报