题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003

Find Metal Mineral

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 4490    Accepted Submission(s): 2071

Problem Description
Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on Mars to collect them, and due to the unknown reasons, the landing site S of all robots is identified in advanced, in other word, all robot should start their job at point S. Each robot can return to Earth anywhere, and of course they cannot go back to Mars. We have research the information of all paths on Mars, including its two endpoints x, y and energy cost w. To reduce the total energy cost, we should make a optimal plan which cost minimal energy cost.
 
Input
There are multiple cases in the input.
In each case:
The first line specifies three integers N, S, K specifying the numbers of metal mineral, landing site and the number of robots.
The next n‐1 lines will give three integers x, y, w in each line specifying there is a path connected point x and y which should cost w.
1<=N<=10000, 1<=S<=N, 1<=k<=10, 1<=x, y<=N, 1<=w<=10000.
 
Output
For each cases output one line with the minimal energy cost.
 
Sample Input
3 1 1
1 2 1
1 3 1
3 1 2
1 2 1
1 3 1
 
Sample Output
3
2

Hint

In the first case: 1->2->1->3 the cost is 3;
In the second case: 1->2; 1->3 the cost is 2;

 
题意:给你一颗有n个节点的树,给出每两个相连节点边的权值(如果你的一个机器人要走这条边花费的能量),再给你k个机器人,问从s点出发,最少花费多少d能量可以遍历所有的节点。
 
思路:一道很好的树形背包的题目,我们可以设立 dp 数组 dp[i][j] 表示节点 i 损失 j 个机器人遍历以节点 i 为根节点组成的子树的所有点所需的最小能量,什么是损失 j 个机器人呢?机器人不是可以来回走的,怎么会损失呢,这是以它最终停留的位置来说 ,我们定义当前节点损失机器人就是机器人从当前节点出发往它的子节点走之后最终没有到当前节点,这就相当于我们这个节点损失了机器人(因为它走之后就没有回来),如果它往子节点走之后又回到当前节点就相当于没有损失机器人(因为你派出它它又回来了,你又可以在当前节点重复利用它)。
 
有了dp数组之后我们怎么来推状态转移方程呢,因为我们要遍历所有的数组,所以节点i来说,我们要遍历它的所有的子节点,即它每个子节点(遍历以该子节点组成的子树的所有点所需的花费)的dp值我们都要取一个,这就是一个多组背包的问题了(每组至少要取一个)(每一组的物品为损失不同机器人数需要的花费的最少能量)。
 
因为是多组背包,为了保证每一组物品都至少取一个,所以我们的在执行递推之前先把当前子节点损失机器人数为0的先加到当前节点的花费里面(这就保证了每组至少取一个),它的状态转移方程就是
 
 
dp[i][j] = dp[i][j] + dp[k][0]+ 2*f[i][k] ;
 
其中 i 表示当前节点,j 代表当前节点损失的机器人数,k 表示当前节点的子节点,f[i][k] 表示i节点到 k 节点的花费,为什么是这样的呢,因为对于当前节点,它要到它的子节点去的时候,它的花费就是子节点的损失加上机器人从当前节点到子节点的花费,因为子节点损失的机器人数为0,那么说明所有机器人都回到了子节点,所以我只要派一个机器人去再让它回来就可以了就可以了。
 
看到上面这段肯定有人会懵,啥,为什么派出去了还要回来?      
 
让我们再深入解析一下我们的dp数组, dp 数组 dp[i][j] 表示当前节点 i 花费它父节点j个机器人来遍历以 i 节点组成的子树的所有节点花费的最少能量(如果它花费 j=0 时表示它花费了父节点0个机器人遍历该子树所有的点所需的最少花费,不就是要回来吗,而那些损失数 j 大于零的,我就没必要遍历完子树的所有节点后再让它们回到 i 节点,因为没必要,会增加能量消耗,反正我要损失掉 i 父节点j 个机器人,它们都不回到 i 节点,不就相当于一开始我们说的 i 节点损失了 j 个机器人吗),这样就可以推出我们的dp方程
dp[i][j]+=max(dp[i][j],dp[i][j-l]+dp[k][l]+l*f[i][k]);
为什么是加 l*f[i][k] 呢,看了上面的解释应该不难理解,就是先从 i 派出 l 个机器人到 k 所需的花费.
 
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct{//链式前向星
int v,w,next;
}edge[];
int head[];
int cnt;
bool vt[];
int dp[][];//dp[i][j]表示节点 i 损失(机器人最后不回到i节点) j 个机器人遍历以节点 i 为根节点组成的子树的所有点所需的最小能量
void add(int u,int v,int w){
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int n,s,m;
void dfs(int k){
for(int i=;i<=m;i++)//初始化为0
dp[k][i]=;
vt[k]=true;
for(int i=head[k];i!=-;i=edge[i].next){
if(!vt[edge[i].v]){
dfs(edge[i].v);//先递归子节点
for(int j=m;j>=;j--){
dp[k][j]+=dp[edge[i].v][]+*edge[i].w;//它儿子的花费的机器人是0,我就要派一个机器人去它那里然后再叫它回来
for(int l=;l<=j;l++){
dp[k][j]=min(dp[k][j],dp[k][j-l]+dp[edge[i].v][l]+edge[i].w*l);//它儿子要花费l个机器人,那我要派l个过去
}
} }
}
}
int main(){
int u,v,w;
while(scanf("%d%d%d",&n,&s,&m)!=EOF){
fill(head,head+,-);//初始化
fill(vt,vt+,false);
cnt=;
for(int i=;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(s);
printf("%d\n",dp[s][m]);
}
return ;
}
 
 
 
 
 

hdu4003详解(树形dp+多组背包)的更多相关文章

  1. CH5402 选课【树形DP】【背包】

    5402 选课 0x50「动态规划」例题 描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了 N(N≤300) 门的选修课程,每个学生可选课程的数量 M 是 ...

  2. 树形DP+(分组背包||二叉树,一般树,森林之间的转换)codevs 1378 选课

    codevs 1378 选课 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond  题目描述 Description 学校实行学分制.每门的必修课都有固定的学分 ...

  3. hdu1561 树形dp,依赖背包

    多重背包是某个物品可以选择多次,要把对物品数的枚举放在对w枚举外面 分组背包是某组的物品只能选一个,要把对每组物品的枚举放在对w枚举内侧 依赖背包是多层的分组背包,利用树形结构建立依赖关系,每个结点都 ...

  4. Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]

    题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...

  5. UVA Live Archive 4015 Cave (树形dp,分组背包)

    和Heroes Of Might And Magic 相似,题目的询问是dp的一个副产物. 距离是不好表示成状态的,但是可以换一个角度想,如果知道了从一个点向子树走k个结点的最短距离, 那么就可以回答 ...

  6. HD1561The more, The Better(树形DP+有依赖背包)

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)

    The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...

  8. poj3345 Bribing FIPA【树形DP】【背包】

    Bribing FIPA Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5910   Accepted: 1850 Desc ...

  9. Android长度单位详解(dp、sp、px、in、pt、mm、dip)

    Android中定义的dimension单位有以下这些:px(Pixels ,像素):对应屏幕上的实际像素点.in(Inches ,英寸):屏幕物理长度单位.mm(Millimeters ,毫米):屏 ...

随机推荐

  1. 树莓派3代刷ubuntu mate在命令行下配置wifi不能连接的一个诡异的bug的解决

    家里路由器不在自己卧室,用树莓派考虑用wifi,之前用Raspberry官方系统,按照教程写的wpa.conf可以连接wifi,后来重新刷ubuntu mate 16.04就不好用了 各种找原因,后来 ...

  2. Java NIO 系列学习(一)Java NIO概述

    参考资料: http://www.importnew.com/19816.html http://ifeve.com/overview/ NIO 三大核心部分: Channel(通道).Buffer( ...

  3. java非阻塞NIO和阻塞IO

    1         非阻塞NIO和阻塞IO 1.1           定义 阻塞IO:线程被阻塞,去处理一个读取和写入,中间如果有等待时间,则线程被占用,也不能处理其他任务: 非阻塞IO(new I ...

  4. Cocos Creator学习三:生命周期回调函数

    1.目的:学习生命周期回调函数以及回调顺序,更有利于我们逻辑的处理把控. 2.生命周期回调函数: 节点:指cc.Node:组件:指cc.Component. ①onLoad:脚本组件绑定的节点所在场景 ...

  5. 如何成为F1车手?

    sorry,玩了几天的GT sport才发现赛车有多难,理论的最佳走线是存在的,但是真实的赛道实在是千变万化,弯道形状角度.高低差.F1还有温度和风速,甚至是路面上的一个碎石都会极大地影响你的成绩.赛 ...

  6. SSM框架完成Ajax简单用户登录验证

    一.前端JSP <%@ page contentType="text/html;charset=UTF-8" language="java" %> ...

  7. 登录获取token,token参数关联至所有请求的请求体内

    问题描述: 有些系统接口判断用户是否登录,是校验登录接口成功后传的token值,也就是请求系统所有接口时,前端传参必带登录成功后接口返回的token,后台以此检验是否过期或是否有登录.所有接口都依赖登 ...

  8. MATLAB 曲线形状,粗细,颜色使用大全

    通过改变R-G-B 的值改变线条的颜色: $$\tt\Large plot(x,y,'Color',[R~~G~~B]);$$ 通过改变$c\in[1,+\infty)$的值改变线条的粗细 $$\tt ...

  9. 在python3里面使用ueditor(基于adminx)

    第一步,下载ueditor,在git上下载 直接download : https://github.com/twz915/DjangoUeditor3/ 然后放到任何一个文件夹里面 配置setting ...

  10. Centos7中网络及设备相关配置

    centos7中,不再赞成使用ifconfig工具,取而代之的是nmcli工具,服务管理也是以systemctl工具取代了service,这些之前版本的工具虽然在centos7中还可以继续使用,只是出 ...