HDOJ 4276 鬼吹灯 (树形DP)
2014-04-08 11:55
239 查看
总结
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] 被重复计算
代码
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 <stdio.h> #include <iostream> #include <string> #include <vector> #include <memory.h> #include <queue> #include <set> #include <algorithm> #include <math.h> 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<Road> 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 pass bool 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<int> 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 ; } /* * 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; }
相关文章推荐
- HDOJ 4276 The Ghost Blows Light(最短路+树形DP)鬼吹灯问题
- hdoj 4276 The Ghost Blows Light 【树形dp】
- HDOJ 4276 The Ghost Blows Light(树形DP)
- HDOJ-4276(树形DP+背包DP)
- HDOJ 4276 The Ghost Blows Light(树形DP)
- HDOJ 题目4276 The Ghost Blows Light(SPFA+树形DP)
- hdu 4276 树形dp + 最短路
- HDU 4276 The Ghost Blows Light (树形DP,变形)
- HDOJ 5325 Crazy Bobo 树形DP
- HDU 4276 The Ghost Blows Light (树形DP)
- hdoj 5834 Magic boy Bi Luo with his excited tree 树形dp
- hdoj--2412 Party at Hali-Bula(树形dp)
- 【树形DP】【HDU 4276】The Ghost Blows Light
- hdoj 1520 Anniversary party 【树形DP入门】
- hdoj Free DIY Tour 1224 (树形DP记录路径)
- HDOJ 4705 Y 树形DP
- HDOJ 4616 - Game/2013多校联合第二场F 树形DP..初始化不能太随意...
- HDOJ题目4705 Y(简单树形DP+数学)
- hdu 4276 The Ghost Blows Light - 树形dp
- HDU 4276 The Ghost Blows Light 树形dp