题目链接: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. vim编辑器-多行加注释与去注释

    在使用vim编辑器时,有时候需要对多行代码进行加注释或去注释,下面将介绍两种方法. 方法一:块选择模式 1. 插入注释 (1)首先按键盘上的ESC进入命令行模式 (2)再按Ctrl+V进入VISUAL ...

  2. Python3爬虫相关软件,库的安装

    Anaconda 百度搜Anaconda清华,根据环境选择版本下载 安装时记得勾选添加到环境变量,不要还要手动添加 Anaconda Navigator可视化界面,可以方便地调用Jupyter等工具. ...

  3. windows,用c++调用mxnet做前向

    参考博客: https://blog.csdn.net/qq_34062105/article/details/82590553 https://blog.csdn.net/u012234115/ar ...

  4. win2008 401 - 未授权: 由于凭据无效,访问被拒绝。解决方法

    iiis中一个小配置的问题,“身份验证”里面“启用匿名身份验证”,编辑匿名身份验证凭据,选中下面的“应用程序池标识”  就可以了

  5. 关于被删以及限制评价后,免费更换新listing的方法

    Prime Day 刚过,review被撸空,还限制留评,之后单量一泻千里,广告都花不出去,没办法,按照网上贴出来的教程自己摸索,居然成功了解除了留评限制,优点是不用移仓,省了一比费用,缺点是list ...

  6. Python函数分类及操作

    为什么使用函数? 答:函数的返回值可以确切知道整个函数执行的结果   函数的定义:1.数学意义的函数:两个变量:自变量x和因变量y,二者的关系                      2.Pytho ...

  7. java小白也能懂的面向对象

    类是对一组具有共同特征和行为的对象的抽象描述. 理解 [1]类是专门用于描述现实生活中的事物的. [2]类描述的事物都具有共同的特征和行为. [3]类就是我们通常所说的 “类型” ,描述的是一个群体性 ...

  8. windows 下 修改jmeter ServerAgent端口

    from:https://blog.csdn.net/wanglha/article/details/51281462 如果想修改UDP和TCP的端口该如何做呢,可以采用如下的方式: CMD命令进入S ...

  9. 20165309 《网络对抗技术》实验五:MSF基础应用

    20165309 <网络对抗技术>实验五:MSF基础应用 1.基础问题回答 (1)什么是exploit? (2)什么是payload? (3)什么是encode? (4)离实战还缺些什么技 ...

  10. oracle性能优化之awr分析

    oracle性能优化之awr分析 作者:bingjava 最近某证券公司系统在业务期间系统运行缓慢,初步排查怀疑是数据库存在性能问题,因此导出了oracle的awr报告进行分析,在此进行记录. 导致系 ...