HDOJ-4276(树形DP+背包DP)
2015-01-13 00:45
281 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4276
好久没有1A过树形DP了,真是开森呢~~~
因为结构是树,所以从1到N肯定会经过最短路径,冗余的时间才能去访问别的节点(并返回最短路径上的节点!!!),因此我选择将这条必然经过的最短路径分离出来,对每个关键节点进行属性DP,再对这条关键路径进行背包DP,具体分析见代码注释。
![](http://img.blog.csdn.net/20150113004034688?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXV1b3VvdWxjeg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
好久没有1A过树形DP了,真是开森呢~~~
因为结构是树,所以从1到N肯定会经过最短路径,冗余的时间才能去访问别的节点(并返回最短路径上的节点!!!),因此我选择将这条必然经过的最短路径分离出来,对每个关键节点进行属性DP,再对这条关键路径进行背包DP,具体分析见代码注释。
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; #define MAX_NODE 111 #define MAX_EDGE 222 #define MAX_TIME 555 /* (1)find critial path from 1 to N, it forms an array path[], with length being M. this can be solved by BFS. (2)we can spend E extra time apart from those on the critial path, so we can find out how much more we can get if we spend 0~E time on each critical nodes' subtree and return to it, say f[i][j] means value we can get if we spend j time on i's subtree and return to i. this is TreeDP with Backpack. (3)now how should we spend E extra time ? this is BackpackDP. say dp(i, j) means the max value we can get if we spend j time on subtrees of path[i,M), then dp(i, j) = max{f[path[i]][k] + dp(i+1, j-k)}, 0 <= k <= j */ int N, T; int value[MAX_NODE]; //value of each node struct Edge{ int to, len, next; } edge[MAX_EDGE]; int cnt, pre[MAX_NODE]; inline void addEdge(int x, int y, int d) { edge[cnt].to = y; edge[cnt].len = d; edge[cnt].next = pre[x]; pre[x] = cnt++; } int dis[MAX_NODE]; //dis[i] = shortest distance from i to N int nex[MAX_NODE]; //nex[i] is i's successive node from i to N int path[MAX_NODE], M, PV; //critial path, its length and its value bool vis[MAX_NODE]; //visited flag queue<int> Q; //bfs queue int f[MAX_NODE][MAX_TIME]; //f[i][j] = max value we can get by spending j time //on subtree of i and return to i except critical path int g[MAX_NODE][MAX_TIME]; //g[i][j] = max value we can get by spending j time //on subtrees of path[i],path[i+1],...,path[M-1] bool init() { if(2 != scanf("%d%d", &N, &T)) return false; cnt = 0; memset(pre+1, -1, N << 2); int i, x, y, d; for(i = 1; i < N; ++i){ scanf("%d%d%d", &x, &y, &d); addEdge(x, y, d); addEdge(y, x, d); } for(i = 1; i <= N; ++i) scanf("%d", value + i); for(int i = 1; i <= N; ++i) memset(f[i], 0, (T+1) << 2); for(int i = 0; i < N; ++i) memset(g[i], -1, (T+1) << 2); return true; } void findPath() { memset(vis + 1, false, N); dis = 0; Q.push(N); vis = true; nex = -1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = pre[x]; i != -1; i = edge[i].next){ int y = edge[i].to; if(vis[y]) continue; nex[y] = x; dis[y] = dis[x] + edge[i].len; vis[y] = true; Q.push(y); } } memset(vis + 1, false, N); M = PV = 0; for(int x = 1; x != -1; x = nex[x]){ // printf("%d ", x); path[M++] = x; PV += value[x]; vis[x] = true; } // printf("\nPath value = %d\n", PV); } void treeDP(int x, int t) { //if vis[x] then x is in critical path, do not count its value here if(!vis[x]) for(int i = 0; i <= t; ++i) f[x][i] = value[x]; vis[x] = true; for(int i = pre[x]; i != -1; i = edge[i].next){ int y = edge[i].to, d = edge[i].len << 1; if(vis[y] || t < d) continue; treeDP(y, t - d); for(int j = t; j >= d; --j)//total time for(int k = 0; k+d <= j; ++k)//spend k time in subtree y f[x][j] = max(f[x][j], f[x][j-d-k] + f[y][k]); } // for(int i = 0; i <= t; ++i) printf("f[%d][%d] = %d\n", x, i, f[x][i]); } int dp(int i, int t) { if(i == M) return 0; if(g[i][t] != -1) return g[i][t]; int ans = 0, x = path[i]; for(int j = 0; j <= t; ++j){ ans = max(ans, f[x][j] + dp(i+1, t-j)); } // printf("g[%d][%d] = %d\n", i, t, ans); return g[i][t] = ans; } void solve() { findPath(); if(dis[1] > T){ puts("0"); return; } int surplus = T - dis[1]; for(int i = 0; i < M; ++i) treeDP(path[i], surplus); printf("%d\n", dp(0, surplus) + PV); } int main() { freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); while(init()) solve(); return 0; }
相关文章推荐
- HDOJ 4276 The Ghost Blows Light(树形DP+背包)
- hdoj 1561 The more, The Better 【树形dp + 01-背包】【入门】
- HDOJ 4276 The Ghost Blows Light(最短路+树形DP)鬼吹灯问题
- HDOJ 1561 - 树形DP,泛化背包
- HDOJ 4276 鬼吹灯 (树形DP)
- *(中等) 树形dp+分组背包 HDU 4276 The Ghost Blows Light
- hdoj 4276 The Ghost Blows Light 【树形dp】
- hdu 4276 树形DP + 分组背包
- HDU 4276 树形dp + 背包
- HDOJ 1561 - 树形DP,泛化背包
- HDOJ 4276 The Ghost Blows Light(树形DP)
- HDU 4276 The Ghost Blows Light [树形背包DP]
- HDU-4276 The Ghost Blows Light (树形DP+背包)
- hdu 4276 树形dp背包
- HDOJ 4276 The Ghost Blows Light(树形DP)
- 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)
- HDU 4276 树形dp+spfa+分组背包
- HDOJ 题目4276 The Ghost Blows Light(SPFA+树形DP)
- HDOJ 4044 - GeoDefense 树形DP..泛化背包转移..
- hdu 4276 The Ghost Blows Light(树形DP+最短路+分组背包)好题。。。