hdu 4616 Game 树形dp
2015-10-10 09:33
411 查看
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4616
题意
有n个房间构成的一棵树,每个房间都有一定价值的礼物,价值可能不相同,有礼物的同时还可能有陷阱,而且每个房间不能重复经过,如果掉入陷阱C次或者没有路可以走了那么游戏结束,求从任意点出发能获得礼物的最大价值。
解题思路
树形dp。
dp[i][j][0] 表示从i的子树上某点出发经过j次陷阱获得的最大价值,且出发点不是陷阱
dp[i][j][1] 表示从i的子树上某点出发经过j次陷阱获得的最大价值,且出发点是陷阱
状态转移为 当j< C 时,
若i是陷阱
dp[i][j+1][flag] = max{dp[son[i]][j][flag] + val[i]};
若i不是陷阱
dp[i][j][flag] = max{dp[son[i]][j][flag] + val[i]};
当j == C时,i肯定不是陷阱,起点肯定是陷阱,否则肯定可以从起点往下继续走,也就是当前dp不是最优的
dp[i][C][1] = max(dp[i][C][1],dp[son[i]][C][1] + val[i]);
最后更新ans的时候,可以看成两条链合并,枚举每条链上陷阱个数,取最优值。
题意
有n个房间构成的一棵树,每个房间都有一定价值的礼物,价值可能不相同,有礼物的同时还可能有陷阱,而且每个房间不能重复经过,如果掉入陷阱C次或者没有路可以走了那么游戏结束,求从任意点出发能获得礼物的最大价值。
解题思路
树形dp。
dp[i][j][0] 表示从i的子树上某点出发经过j次陷阱获得的最大价值,且出发点不是陷阱
dp[i][j][1] 表示从i的子树上某点出发经过j次陷阱获得的最大价值,且出发点是陷阱
状态转移为 当j< C 时,
若i是陷阱
dp[i][j+1][flag] = max{dp[son[i]][j][flag] + val[i]};
若i不是陷阱
dp[i][j][flag] = max{dp[son[i]][j][flag] + val[i]};
当j == C时,i肯定不是陷阱,起点肯定是陷阱,否则肯定可以从起点往下继续走,也就是当前dp不是最优的
dp[i][C][1] = max(dp[i][C][1],dp[son[i]][C][1] + val[i]);
最后更新ans的时候,可以看成两条链合并,枚举每条链上陷阱个数,取最优值。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <vector> #include <map> #include <set> #include <cmath> #include <algorithm> #include <functional> #include <cmath> #include <bitset> using namespace std; typedef long long LL; const int inf = 1<<28; const int maxn = 50010; struct Edge{ int to,next,w; }e[maxn*2]; bool trap[maxn]; LL val[maxn]; int head[maxn],cnt; int N,C; LL dp[maxn][5][2]; LL ans; void init(){ cnt = 0; memset(head,-1,sizeof(head)); } void add(int u,int v){ e[cnt].to = v; e[cnt].next = head[u]; head[u] = cnt++; } void dfs(int u,int fa){ for(int i=0;i<=C;i++){ dp[u][i][0] = dp[u][i][1] = -inf; } dp[u][trap[u]][trap[u]] = val[u]; for(int i=head[u]; i!=-1; i=e[i].next){ int v = e[i].to; if(v == fa) continue; dfs(v,u); for(int j=0;j<=C;j++){ for(int k=0;k+j<=C;k++){ if(j<C) ans = max(ans,dp[u][j][0] + dp[v][k][1]); if(k<C) ans = max(ans,dp[u][j][1] + dp[v][k][0]); if(j+k < C) ans = max(ans,dp[u][j][0] + dp[v][k][0]); } } for(int j=0;j<C;j++){ dp[u][j+trap[u]][0] = max(dp[u][j+trap[u]][0], dp[v][j][0] + val[u]); dp[u][j+trap[u]][1] = max(dp[u][j+trap[u]][1], dp[v][j][1] + val[u]); } if(!trap[u]) dp[u][C][1] = max(dp[u][C][1], dp[v][C][1]+val[u]); } } int main(){ int T; cin >> T; while(T--){ cin >> N >> C; init(); for(int i=0;i<N;i++) cin >> val[i] >> trap[i]; int u,v; for(int i=0;i<N-1;i++){ cin >> u >> v; add(u,v); add(v,u); } ans = 0; dfs(0,-1); cout << ans << endl; } return 0; }
相关文章推荐
- jquery页面加载成功后自动执行
- linux发行版i386i686x86-64的区别
- 安装mysql数据库
- Swift2.1 语法指南——函数
- Go之类型判断
- 保存处理后的视频文件
- Android实现推送方式解决方案
- eclipse调试以及各个键的作用
- perl客户需求设置自动生成
- SAP 调用外部程序 (NCO、JCO)
- 数据库事务隔离级别和锁实现机制
- 安装和部署ZkeaCMS
- 是否该放弃东莞的工作
- PLM系统与选择
- 在C++ 中 如何调用 C# 写的DLL
- Code Forces 584 A. Olesya and Rodion(水~)
- 使用Scrapy爬取大众点评图片
- 最佳实践:AtomicInteger实现边界值控制
- bootstrap+jQuery.validate
- jqTransform美化表单