题目链接:https://www.luogu.org/problem/show?pid=3360
题解:我们用f[i][j]来表示以i为根的子树上给定j的时间能获得的价值,需要记忆化搜索。
(如果是走廊)f[i][j]=max(f[i][j],f[lson][k]+f[rson][j-k-2*time[i]);
(如果尽头是画就进行01背包)程序具体有些细节,我在程序注释中写
程序:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; int tot,m,b[500]; LL f[500][1000],a[500]; void dfs(int now) { int x,y; scanf("%d%d",&x,&y); x=x*2;//因为无论如何要走的话,这条走廊是要走两遍的 if (y) //如果说尽头是画的话,就预先处理好01背包 { for (int i=1;i<=y;i++) scanf("%lld%d",&a[i],&b[i]); for (int i=1;i<=y;i++) for (int j=m;j>=b[i]+x;j--) f[now][j]=max(f[now][j],f[now][j-b[i]]+a[i]); } else {//否则深搜左右儿子 tot++; int l=tot; dfs(tot); tot++; int r=tot; dfs(tot); for (int i=x;i<=m;i++) for (int j=0;j<=i-x;j++) f[now][i]=max(f[now][i],f[l][j]+f[r][i-j-x]); //进行dp } } int main() { tot=1; scanf("%d",&m); m--; dfs(1); printf("%lld ",f[1][m]); return 0; }