题目链接: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. git\CentOS6.5中gitlab安装教程

    一.Git 起源: Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本 ...

  2. docker笔记(3) ------Django项目的docker部署

    2019-01-12   14:23:18 django容器连接到mysql_server容器分析:原myblog项目使用sqlit3数据库,使用mysql容器前需要在django中加入pymysql ...

  3. [C#]将数据写入已存在的excel文件

    测试如下(xls/xlsx): //将数据写入已存在Excel public static void writeExcel(string result, string filepath) { //1. ...

  4. [冷知识] 连字符-减号-横杠的区别 difference between hyphen-minus-dash

    因为早期打印机等宽的原因, 连字符和减号都是 -, 叫做hyphen-minus ,对应Unicode: U+002D(ASCII也是). 现在减号可以是:U+2212, 但编程语言中还是习惯使用U+ ...

  5. rocketMQ No route info of this topic 错误

    最近在使用rocketmq 发送消息,出现了No route info of this topic 异常,但奇怪的是我的其它的服务都可以成功发送,唯有crs服务不能成功发送,在网上搜索的解决方式基本上 ...

  6. elementUi中的计数器ele-mumber中的change事件传参及事件调用

    业务场景是需要在点击业务工作量的时候设置任务工作量这一项的评分不能大于任务质量及任务时限的权重之和除以二 上代码 JS逻辑代码 因出现弹出层提示后设置输入框的值如果大于sum的值,设置输入的值为sum ...

  7. 记一次Debug过程

    刚刚加入新公司,就迎来第一场战斗,微服务拉入拉出测试. 简单的说,对于接入eureka 和 vi(携程开源的) 应用,在使用发布系统进行发布的时候,会经过这么一个流程   UP —— STARTING ...

  8. LeGO-LOAM编译、运行

    LeGO-LOAM Github 地址:https://github.com/RobustFieldAutonomyLab/LeGO-LOAM 相关依赖安装 1. ROS 2.GTSAM 下载gtsa ...

  9. git相关操作记录

    拉取远端并强制覆盖本地文件 有时候会出现想放弃本地修改的情况,那么只需要下面几行命令 git fetch --all git reset --hard origin/master git pull / ...

  10. springboot整理

    lombok 添加maven依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId& ...