codevs 1378 选课 (树形DP)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,son[310][2],f[310][310],v[310],ans,falg; int init() { int x=0;char s;s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int DP(int p,int x) { if(x==0||(p==0&&falg==1))return 0; falg=1; if(f[p][x])return f[p][x]; int maxx=0; f[p][x]=v[p]; for(int i=1;i<=x;i++) { maxx=max(maxx,DP(son[p][1],x-i)+v[p]+DP(son[p][2],i-1)); maxx=max(maxx,DP(son[p][2],x)); } if(maxx>f[p][x])f[p][x]=maxx; return f[p][x]; } int main() { n=init();m=init(); int x,y; for(int i=1;i<=n;i++) { x=init();y=init(); v[i]=y; if(son[x][1]==0)//左孩子空 直接放上 { son[x][1]=i; continue; } int fa=son[x][1];//左孩子不空 i要放到左孩子的右孩子上 while(son[fa][2])fa=son[fa][2];//一直放到空的地方 son[fa][2]=i; } printf("%d\n",DP(0,m+1));//多加一个节点0 把森林变为树 同时科目数+1 }