Starship Troopers

Problem Description
You, the leader of Starship Troopers, are sent to destroy a base of the bugs. The base is built underground. It is actually a huge cavern, which consists of many rooms connected with tunnels. Each room is occupied by some bugs, and their brains hide in some of the rooms. Scientists have just developed a new weapon and want to experiment it on some brains. Your task is to destroy the whole base, and capture as many brains as possible.

To kill all the bugs is always easier than to capture their brains. A map is drawn for you, with all the rooms marked by the amount of bugs inside, and the possibility of containing a brain. The cavern's structure is like a tree in such a way that there is one unique path leading to each room from the entrance. To finish the battle as soon as possible, you do not want to wait for the troopers to clear a room before advancing to the next one, instead you have to leave some troopers at each room passed to fight all the bugs inside. The troopers never re-enter a room where they have visited before.

A starship trooper can fight against 20 bugs. Since you do not have enough troopers, you can only take some of the rooms and let the nerve gas do the rest of the job. At the mean time, you should maximize the possibility of capturing a brain. To simplify the problem, just maximize the sum of all the possibilities of containing brains for the taken rooms. Making such a plan is a difficult job. You need the help of a computer.

 
Input
The input contains several test cases. The first line of each test case contains two integers N (0 < N <= 100) and M (0 <= M <= 100), which are the number of rooms in the cavern and the number of starship troopers you have, respectively. The following N lines give the description of the rooms. Each line contains two non-negative integers -- the amount of bugs inside and the possibility of containing a brain, respectively. The next N - 1 lines give the description of tunnels. Each tunnel is described by two integers, which are the indices of the two rooms it connects. Rooms are numbered from 1 and room 1 is the entrance to the cavern.

The last test case is followed by two -1's.

 
Output
For each test case, print on a single line the maximum sum of all the possibilities of containing brains for the taken rooms.

 
Sample Input
5 10
50 10
40 10
40 20
65 30
70 30
1 2
1 3
2 4
2 5
1 1
20 7
-1 -1
 
Sample Output
50
7
 
Author
XU, Chuan
 
Source
 
Recommend
JGShining
 
  
     
说实话,第一次做树形dp这类题目,答案参考网上做的,有点头疼,应该做多了就好了吧,凡事都是熟能生巧!    

有 n(1<n<=100) 个山洞,每个山洞中都有一些 bug,每个山洞中都有一定的概率包含一个 brain。所有的山洞形成一棵树,现在给你 m(0<=m<=100) 个士兵,每个士兵都能消灭 20 个 bugs,并占领这个山洞,山洞的入口的编号是 1,问怎么安排士兵占领山洞才能使捕获 brain 的概率最大!

典型的树上背包问题

定义状态 f[u][P] 表示用 P 个士兵占领以 u 为根节点的子树所能获得的概率最大值,状态转移就是一个树形DP过程,目标状态就是 f[1][m]。

f[u][p] = max {f[u][p], f[u][p - k] + f[v][k] };其中v是u的子节点。

代码如下:

/*比较苦逼的树形DP,慢慢来吧!不着急*/
#include <iostream>
#include <vector>
using namespace std;
const int SIZE = 105; int roomNumber, trooperNumber;
int cost[SIZE], brain[SIZE];
int dp[SIZE][SIZE]; /*dp[u][p]表示用 P 个士兵占领以 u 为根节点的子树所能获得的概率最大值*/
vector<int> adj[SIZE]; /*图*/ void dfsPulsDp(int p, int pre)
{
for (int i = cost[p]; i <= trooperNumber; ++i) /*初始化,首先将dp[p][i]里面填充进brain[p],后面可以更新dp[p][i]的值*/
dp[p][i] = brain[p]; /*也就是说当我们有cost[p]名队员以至于更多时,我们最少可以获得brain[p]个大脑*/
int num = adj[p].size(); /*num指p节点含有的支路数*/
for (int i = 0; i < num; ++i) /*一条支路一条支路遍历,也就是所谓的dfs*/
{
int v = adj[p][i];
if (v == pre) continue; /*避免死循环,节点如果是根部,就继续*/
dfsPulsDp (v, p); /*递归解决问题,先将子节点的所能得到的最大值计算出来*/ for (int j = trooperNumber; j >= cost[p]; --j) /*当队员人数一定时*/
for (int k = 1; k <= j - cost[p]; ++k) /*由于p节点一定要通过,所以一定要花费cost[p]*/
if (dp[p][j] < dp[p][j - k] + dp[v][k])
{/*v节点就两种状态,要么选择,要么不选择,选择的话dp[p][j] = dp[p][j - k] + dp[v][k],不选择的话就不变*/
dp[p][j] = dp[p][j - k] + dp[v][k];
}
}
} int main()
{
while ((cin >> roomNumber >> trooperNumber) && (roomNumber != -1) && (trooperNumber != -1))
{
int bug, bi1, bi2;
int i;
for (i = 0; i < roomNumber; i++)
{
cin >> bug >> brain[i];
cost[i] = (bug + 19) / 20;
}
for (i = 0; i < roomNumber; i++)
adj[i].clear(); for (i = 0; i < roomNumber - 1; i++)
{
cin >> bi1 >> bi2;
adj[bi1 - 1].push_back(bi2 - 1);
adj[bi2 - 1].push_back(bi1 - 1);
} if (trooperNumber == 0)
{
cout << '0' << endl;
continue;
} memset(dp, 0, sizeof(dp));
dfsPulsDp(0, -1);
cout << dp[0][trooperNumber] << endl;
}
return 0;
}

杭电OJ——1011 Starship Troopers(dfs + 树形dp)的更多相关文章

  1. HDU 1011 Starship Troopers【树形DP/有依赖的01背包】

    You, the leader of Starship Troopers, are sent to destroy a base of the bugs. The base is built unde ...

  2. hdu 1011(Starship Troopers,树形dp)

    Starship Troopers Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  3. HDU-1011 Starship Troopers(树形dp)

    Starship Troopers Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  4. 『ACM C++』HDU杭电OJ | 1416 - Gizilch (DFS - 深度优先搜索入门)

    从周三课开始总算轻松了点,下午能在宿舍研究点题目啥的打一打,还好,刚开学的课程还算跟得上,刚开学的这些课程也是复习以前学过的知识,下半学期也不敢太划水了,被各种人寄予厚望之后瑟瑟发抖,只能努力前行了~ ...

  5. hdu 1011 Starship Troopers (树形背包dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接 : hdu-1011   题意 有n个洞穴编号为1-n,洞穴间有通道,形成了一个n-1条边的树, 洞穴的入口即 ...

  6. HDU-1011 Starship Troopers (树形DP+分组背包)

    题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<i ...

  7. C#利用POST实现杭电oj的AC自动机器人,AC率高达50%~~

    暑假集训虽然很快乐,偶尔也会比较枯燥,,这个时候就需要自娱自乐... 然后看hdu的排行榜发现,除了一些是虚拟测评机的账号以外,有几个都是AC自动机器人 然后发现有一位作者是用网页填表然后按钮模拟,, ...

  8. 杭电oj 2095 & 异或^符号在C/C++中的使用

    异或^符号,在平时的学习时可能遇到的不多,不过有时使用得当可以发挥意想不到的结果. 值得注意的是,异或运算是建立在二进制基础上的,所有运算过程都是按位异或(即相同为0,不同为1,也称模二加),得到最终 ...

  9. 用python爬取杭电oj的数据

    暑假集训主要是在杭电oj上面刷题,白天与算法作斗争,晚上望干点自己喜欢的事情! 首先,确定要爬取哪些数据: 如上图所示,题目ID,名称,accepted,submissions,都很有用. 查看源代码 ...

随机推荐

  1. Microsoft .NET Pet Shop 简介

    最初研究 .NET Pet Shop 的目的是用 Microsoft .NET 实现 Sun 主要的 J2EE 蓝图应用程序 Sun Java Pet Store 同样的应用程序功能. 根据用 .NE ...

  2. 解决wps for linux 中文输入法光标不跟随的问题

    需要安装qt4-qtconfig和ibus-qt4,安装ibus-qt4之后才能在qt4-qtconfig“界面”选项卡默认输入法选项中看到ibus,选定它,然后设置XIM输入风格为光标跟随风格,保存 ...

  3. leetcode第22题--Merge k Sorted Lists

    problem:Merge k sorted linked lists and return it as one sorted list. Analyze and describe its compl ...

  4. memcpy源代码

    7月22号去面试开发的职位,面试官先问我在以前项目中写了什么程序.我就巴拉巴拉的说了一堆写过的code,主要还是测试工具和自动化测试代码.之后让我写memcpy的函数,面试官还挺好的,帮我把函数原型都 ...

  5. 异步陷阱之IO

    异步陷阱之IO篇 很多教程和资料都强调流畅的用户体验需要异步来辅助,核心思想就是保证用户前端的交互永远有最高的优先级,让一切费时的逻辑通通放到后台,等到诸事完备,通知一下前端给个提示或者继续下一步.随 ...

  6. KNN算法的理解

    一.算法 1.kNN算法又称为k近邻分类(k-nearest neighbor classification)算法. 最简单平庸的分类器或许是那种死记硬背式的分类器,记住全部的训练数据.对于新的数据则 ...

  7. Android项目---快递查询

    快递查询,快递100上有更多接口信息 1.快递查询的接口是 快递公司的code值+快递单号 进行的网络查询.第一步,怎么将快递公司的名字转换成code值,传递给接口.下面是快递公司以及对应的code值 ...

  8. Android项目----AsyncTask异步操作

    public abstract class AsyncTask extends Object java.lang.Object    ↳ android.os.AsyncTask<Params, ...

  9. Oracle左连接,右连接

    Oracle左连接,右连接 数据表的连接有: 1.内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现 2.外连接: 包括 (1)左外连接(左边的表不加限制) (2)右外连接(右边的表不加限制 ...

  10. jsonp总结

    由于“同源策略”的限制,ajax不能做跨域请求,jsonp是当下解决跨域请求最流行的方案,来个例子(index.html): <!doctype html> <html lang=& ...