HDOJ-1011(树形DP)
来源:互联网 发布:联网监控软件 编辑:程序博客网 时间:2024/06/07 22:54
容易想到状态方程:f[i][j] = max(f[i][j], f[child[i][k] + f[i][j - k]), 但一开始没有注意到很多细节,WA了几次之后看了discuss之后才了解:
(0)有些节点不需要留下trooper,但我们仍然需要派遣至少1个trooper去这些节点
(1)我们必须先攻克父节点才能进入子节点(必须在父节点留够充分的troopers才能进入下一个节点)
(2)进入子节点的时候我们必须携带至少1个的troopers,尽管一些节点并不需要留下trooper
下面是标准的读入、建树、DP过程:
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;int N, M;struct Node{ int cost, gain; vector<int> children;} arr[101];//tree structureint gain[101][101];//best[i][j] is for subtree with root being node i, //with j money in total, how many gains we can getvector<int> tmp[101];//temporary save of bidirectional connectionsbool vis[101]; //visited flags of each nodevoid buildTree(int i){ vis[i] = true; const vector<int>& v = tmp[i]; for(int k = 0, s = v.size(); k < s; ++k){ int adj = v[k]; if(vis[adj]) continue; arr[i].children.push_back(adj); buildTree(adj); }}bool input(){ scanf("%d %d", &N, &M); if(N < 0) return false;//input node info for(int i = 1; i <= N; ++i){ scanf("%d %d", &arr[i].cost, &arr[i].gain); int q = arr[i].cost / 20; if(arr[i].cost % 20) arr[i].cost = q + 1; else arr[i].cost = q; //initialize vis[i] = false; tmp[i].clear(); arr[i].children.clear(); memset(gain[i], 0, (M + 1) << 2); }//input connection info int from, to; for(int i = 1; i < N; ++i){ scanf("%d %d", &from, &to); tmp[from].push_back(to); tmp[to].push_back(from); }//build tree start from 1 buildTree(1); return true;}void postDP(int i){ const vector<int>& v = arr[i].children; int child, money, j, k = 0, s = v.size();//before traverse to subtrees for(money = arr[i].cost; money <= M; ++money) gain[i][money] = arr[i].gain;//post traverse for(; k < s; ++k){ child = v[k]; postDP(child); //zero one pack with child v[k] //we need to leave enough money to pay for this gate for(money = M; money >= arr[i].cost; --money){ //this gate may take no money, and we must take at least 1 unit to next gate for(j = 1; j <= money - arr[i].cost; ++j){ gain[i][money] = max(gain[i][money], gain[child][j] + gain[i][money - j] ); } } }}int main(){ while(input()){ if(M == 0){ puts("0"); continue; } postDP(1); printf("%d\n", gain[1][M]); } return 0;}但实际上我们并不需要明确的建树过程:
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;int N, M;struct Node{ int cost, gain; vector<int> children;} arr[101];//tree structureint gain[101][101];//best[i][j] is for subtree with root being node i, //with j money in total, how many gains we can getbool vis[101];bool input(){ scanf("%d %d", &N, &M); if(N < 0) return false;//input node info for(int i = 1; i <= N; ++i){ scanf("%d %d", &arr[i].cost, &arr[i].gain); int q = arr[i].cost / 20; if(arr[i].cost % 20) arr[i].cost = q + 1; else arr[i].cost = q; //initialize vis[i] = false; arr[i].children.clear(); memset(gain[i], 0, (M + 1) << 2); }//input connection info int from, to; for(int i = 1; i < N; ++i){ scanf("%d %d", &from, &to); arr[from].children.push_back(to); arr[to].children.push_back(from); } return true;}void postDP(int i){ vis[i] = true; const vector<int>& v = arr[i].children; int child, money, j, k = 0, s = v.size();//before traverse to subtrees for(money = arr[i].cost; money <= M; ++money) gain[i][money] = arr[i].gain;//post traverse for(; k < s; ++k){ child = v[k]; if(vis[child]) continue; postDP(child); //zero one pack with child v[k] //we need to leave enough money to pay for this gate for(money = M; money >= arr[i].cost; --money){ //this gate may take no money, and we must take at least 1 unit to next gate for(j = 1; j <= money - arr[i].cost; ++j){ gain[i][money] = max(gain[i][money], gain[child][j] + gain[i][money - j] ); } } }}int main(){ while(input()){ if(M == 0){ puts("0"); continue; } postDP(1); printf("%d\n", gain[1][M]); } return 0;}
虽然A了,但是感觉好奇怪,明明空间和时间都需要的少了,judge的时候反而比前面的程序需要更多的空间和时间……
0 0
- HDOJ-1011(树形DP)
- HDOJ 1011 树形DP
- HDOJ-1561(树形DP)
- HDOJ-4276(树形DP+背包DP)
- HDOJ 1011 Starship Troopers(树形DP)
- HDOJ 题目4714 Tree2cycle(树形DP)
- hdoj 2196Computer 树形DP
- computer hdoj 2196树形dp
- HDOJ 4705 Y 树形DP
- 【树形DP】 HDOJ 5148 Cities
- hdoj 1011 Starship Troopers 【树形DP + 01背包】
- HDOJ 1561 The more, The Better (树形DP)
- HDOJ (HDU) 1561 The more, The Better (树形DP)
- hdoj - 1520 - Anniversary party(基础树形DP)
- HDOJ 题目1520 Anniversary party(树形dp)
- HDOJ题目4705 Y(简单树形DP+数学)
- hdoj Free DIY Tour 1224 (树形DP记录路径)
- hdu 1011(树形DP)
- log_archive_dest_n和standby_archive_dest
- $q & promise service
- 有线 无线同时使用的相关问题
- Python网络爬虫抓取糗事百科
- Java 8的五大特性,将改变你的代码之路
- HDOJ-1011(树形DP)
- 不忘初心,玉汝于成
- 京东获取订单的接口
- 初探C++异常处理学习笔记
- Linux常用的命令
- DATEDIFF 函数 [日期和时间]
- 计算机网络(一)
- tinyMCE粘贴word/html时去掉文本里的样式
- Android 的媒体路由功能应用与框架解析