博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDOJ 4276 鬼吹灯 (树形DP)
阅读量:5810 次
发布时间:2019-06-18

本文共 2971 字,大约阅读时间需要 9 分钟。

 

总结

1. dp[u][k] 是恰好用完 k 时间的最大价值

2. dfs(u, pre, vmax) 是计算 dp[u][1...vmax] 的值

3. dfs 内部遍历, j 从大到小, 防止重复计算 f(j) = g(j-k)

而 k 是从小到大, 因为在 134 行,  dp[j] = max(dp[j], dp[j-k]+dp'[k]) 比较特殊, k 可以等于 0. 导致 dp[j] 被重复计算

 

代码

/* * source.cpp * *  Created on: Apr 6, 2014 *      Author: sangs */#include 
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;class Road {public: int to, cost; Road(int _to, int _cost):to(_to), cost(_cost) {} Road() { to = cost = 0; } bool operator <(const Road &rhs) const { return this->cost < rhs.cost; }};vector
graph[1000];int val[1000];int dp[1000][1000];const int INF = 0X3F3F3F3F;int dist[1000];int father[1000];bool mark[1000]; // mark those nodes must passbool visited[1000];/* * calculate the shortest path from 1 to n * as well as those nodes in shortest path * SPFA algorithm */int bfs(int n) { queue
record; memset(visited, 0, sizeof(visited)); memset(mark, 0, sizeof(mark)); memset(dist, 0x3f, sizeof(dist)); record.push(1); dist[1] = 0; father[1] = -1; while(!record.empty()) { int thisNode = record.front(); record.pop(); for(size_t i = 0; i < graph[thisNode].size(); i ++) { int j = graph[thisNode][i].to; //cout << j << " " << dist[i] << " " << graph[thisNode][i].cost << endl; if(dist[thisNode] + graph[thisNode][i].cost < dist[j]) { dist[j] = dist[thisNode] + graph[thisNode][i].cost; father[j] = thisNode; record.push(j); } } } for(int i = n; i != -1; i = father[i]) { mark[i] = 1; } return dist[n];}/* * tree_dp to calculate dp[u][1...vmax] * dp[u][k] is the maximum income when assigned k time to node u and get back to u * pre is u's father */void tree_dp(int u, int pre, int vmax) { dp[u][0] = val[u]; for(size_t i = 0; i < graph[u].size(); i ++) { // enum v's child int index = graph[u][i].to; if(index == pre) continue; if(mark[index]) continue; tree_dp(index, u, vmax); int cost = graph[u][i].cost; for(int j = vmax; j >= 0; j --) { for(int k = 0; k <= j-2*cost; k ++) { dp[u][j] = max(dp[u][j], dp[u][j-k-2*cost]+dp[index][k]); } } }}int main() { freopen("input.txt", "r", stdin); int n, T; while(scanf("%d%d", &n, &T) != EOF) { for(int i = 0; i <= n+10; i ++) graph[i].clear(); for(int i = 0; i < n-1; i ++) { int from, to, cost; scanf("%d%d%d", &from, &to, &cost); graph[from].push_back(Road(to, cost)); graph[to].push_back(Road(from, cost)); } for(int i = 1; i <= n; i ++) scanf("%d", val+i); int cutTime = bfs(n); T -= cutTime; memset(dp, 0, sizeof(dp)); dp[n+1][0] = 0; for(int i = 1; i <= n; i ++) { if(mark[i] == 0) continue; tree_dp(i, n+1, T); for(int j = T; j >= 0; j --) { for(int k = 0; k <= j; k ++) { //for(int k = j; k >= 0; k --) { dp[n+1][j] = max(dp[n+1][j], dp[n+1][j-k] + dp[i][k]); } } } int res = 0; for(int i = 0; i <= T; i ++) res = max(res, dp[n+1][i]); printf("%d\n", res); } return 0;}

  

  

转载于:https://www.cnblogs.com/zhouzhuo/p/3651652.html

你可能感兴趣的文章
Event事件的兼容性(转)
查看>>
CQRS学习——一个例子(其六)
查看>>
Hadoop 学习资料集锦
查看>>
12.22 repeater 添加
查看>>
leetcode-74-搜索二维矩阵
查看>>
Remote Desktop Issues
查看>>
IIS7内建账号,应用程序池
查看>>
之字形打印矩阵
查看>>
我的2014-相对奢侈的生活
查看>>
zoj 2412 dfs 求连通分量的个数
查看>>
NLP自然语言处理学习笔记一(环境准备)
查看>>
李开复:中国第四波创业浪潮来临
查看>>
dl以及dt,dd,以及table的tr,th,td最清楚分析
查看>>
js 数据类型问题
查看>>
STL学习小结
查看>>
ORACLE数据库常用查询二
查看>>
VMware-workstation-full-11.0.0-2305329&VMware-player-7.0.0-2305329
查看>>
careercup-C和C++ 13.10
查看>>
Hadoop集群(第10期)_MapReduce与MySQL交互
查看>>
使用Java高速实现进度条
查看>>