选课
这道题目给出的数据是以树形结构连接的。
这题比苹果树(题目传送门)多了一个步骤就是把一棵多叉树转化为二叉树。
读入数据时把二叉树建好:把一门课的先修课作为它的父亲。一个结点的第一个孩子作为自己的左子树,其它孩子作为第一个孩子的最右树枝链,即分别做第一个孩子的右儿子、右儿子的右儿子……(左儿子右兄弟表示法)
#include<iostream> #include<cstdio> using namespace std; int n,m; struct node{ int lson,rson; }a[305]; bool gotson[305]; int dp[305][305],s[305]; void DP(int rc,int rm) {//if一定要打,要不然会回到虚根导致dp错误 if(dp[rc][rm]) return; if(a[rc].rson) DP(a[rc].rson,rm); dp[rc][rm]=dp[a[rc].rson][rm]; for(int k=1;k<=rm;k++){ if(a[rc].lson) DP(a[rc].lson,k-1); if(a[rc].rson) DP(a[rc].rson,rm-k); dp[rc][rm]=max(dp[rc][rm],dp[a[rc].lson][k-1]+dp[a[rc].rson][rm-k]+s[rc]); } } int main(void) { scanf("%d%d",&n,&m); for(int i=1,k;i<=n;++i) { scanf("%d%d",&k,s+i); if(gotson[k]) { k=a[k].lson; while(a[k].rson) k=a[k].rson;//找最深的右儿子 a[k].rson=i; } else { gotson[k]=1;a[k].lson=i; }//多叉转二叉树 } DP(0,m+1); printf("%d",dp[0][m+1]); }