[树形DP]JZOJ 5788 餐馆
分析
这题比赛时并没有想做,因为折返的骚操作让我想不到怎么搞方程(其实一开始列的方程还是挺像正解的233)
设f[i][j][0/1]表示以i为根的子树用了j的单位时间有/无到达根的最大收益,方程显然:
f[u][j][1]+f[v][k][0]→f[u][j+k+1][1]
f[u][j][0]+f[v][k][1]→f[u][j+k+2][1]
f[u][j][0]+f[v][k][0]→f[u][j+k+2][0]
然后这样是O(n2)可以证明,这里不做过多叙述

#include <iostream> #include <cstdio> using namespace std; const int N=501; struct Edge { int u,v,nx; }g[2*N]; int cnt,list[N]; int f[N][N][2]; int a[N],d[N]; int n,m; void Add(int u,int v) { g[++cnt].u=u;g[cnt].v=v;g[cnt].nx=list[u];list[u]=cnt; } void Init() { scanf("%d%d",&n,&m); for (int i=0;i<n;i++) scanf("%d",&a[i+1]); for (int i=0;i<n-1;i++) { int u,v; scanf("%d%d",&u,&v); Add(u,v);Add(v,u); } } void Dfs(int u,int fa) { for (int i=list[u];i;i=g[i].nx) if (g[i].v!=fa) { Dfs(g[i].v,u); for (int j=m;j>=0;j--) for (int k=0;k<=m;k++) { if (j-k-2<0) break; f[u][j][1]=max(f[u][j][1],f[u][j-k-2][1]+f[g[i].v][k][0]); } for (int j=m;j>=0;j--) for (int k=0;k<=m;k++) { if (j-k-1<0) break; f[u][j][1]=max(f[u][j][1],f[u][j-k-1][0]+f[g[i].v][k][1]); } for (int j=m;j>=0;j--) for (int k=0;k<=m;k++) { if (j-k-2<0) break; f[u][j][0]=max(f[u][j][0],f[u][j-k-2][0]+f[g[i].v][k][0]); } } for (int i=m;i>=1;i--) f[u][i][0]=max(f[u][i][0],f[u][i-1][0]+a[u]), f[u][i][1]=max(f[u][i][1],f[u][i-1][1]+a[u]); } int main() { freopen("dostavljac.in","r",stdin); freopen("dostavljac.out","w",stdout); Init(); Dfs(1,0); printf("%d",max(f[1][m][0],f[1][m][1])); fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。
分类:
DP-树形DP
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· MQ 如何保证数据一致性?