Find Metal Mineral

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

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;

dp[pos][num]表示以pos为根节点的子树下,用去num个机器人,所得到的最小值

特别的是当num==0的时候,dp[pos][0]表示用一个机器人去走完所有子树,最后又回到pos这个节点

状态转移:dp[pos][num]=min∑{dp[pos_j][num_j]+w_j},pos_j是pos的所有儿子,

当num_j==0的时候,和别的时候不同,特别处理一下就好。

状态转移并不难,最精华的,我不认为是状态转移,而是转移时使用的那个“分组背包”思想。

使用一维数组的“分组背包”伪代码如下:

for 所有的组i

for v=V..0

for 所有的k属于组i

f[v]=max{f[v],f[v-c[k]]+w[k]}

上面那个状态转移时,要把num个机器人分给所有它的儿子,状态太多了,不好做,用“分组背包”实在太帅了。
 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; struct Edge{
int to;
int value;
int next;
}edge[*];
int head[],dp[][];
int N,S,K,total; inline int MIN(int a,int b)
{
if(a<b) return a;
return b;
}
void addEdge(int start,int end,int value)
{
edge[total].to=end;edge[total].value=value;
edge[total].next=head[start];head[start]=total++; edge[total].to=start,edge[total].value=value;
edge[total].next=head[end],head[end]=total++;
} void DP(int source,int pre)
{
for(int i=head[source];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(to==pre) continue;
DP(to,source);
for(int j=K;j>=;j--)
{
dp[source][j]+=dp[to][]+*edge[i].value;
for(int k=;k<=j;k++)
dp[source][j]=MIN(dp[source][j],dp[source][j-k]+dp[to][k]+k*edge[i].value);
}
}
} int main()
{
while(scanf("%d %d %d",&N,&S,&K)!=EOF)
{
memset(dp,,sizeof(dp));
memset(head,-,sizeof(head));
total=; int x,y,cost;
for(int i=;i<N;i++)
{
scanf("%d %d %d",&x,&y,&cost);
addEdge(x,y,cost);
}
DP(S,-);
printf("%d\n",dp[S][K]);
}
return ;
}

思路和其他人差不多,谈谈自己是怎么理解的吧:
     首先,用两数组建立无向树,还是第一次,费了不少功夫。定义一个结构代表边edge[i]={to,next,value},其中edge[i]表示第i条边,to是边的末点,value就不说了,next代表的是同一父节点边方向相同的与此边相邻的左边的边的编号,其中最左是-1。以此为基础建立一个边数组(注意数组大小是顶点数的两倍),还有用一个head[i]数组来表示最右边的边的编号。

  解释这一段代码,当时写的理解的不是很好:

 void DP(int source,int pre)
{
for(int i=head[source];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(to==pre) continue;
DP(to,source);
for(int j=K;j>=;j--)
{
dp[source][j]+=dp[to][]+*edge[i].value;
for(int k=;k<=j;k++)
dp[source][j]=MIN(dp[source][j],dp[source][j-k]+dp[to][k]+k*edge[i].value);
}
}
}

第一层for循环查找与节点source相连的各条边,to是此边对应的末点,若此边是叶子节点则to==pre(由于节点最左边的边访问完以后,只有到他父节点的边,这里只能用continue,因为不确定访问的顺序,return不合适),递归访问子节点此时应用01背包,由于dp[source][0]比较特殊单独处理,一棵子树对应一个分组,dp[source][j]=MIN(dp[source][j],dp[source][j-k]+dp[to][k]+k*edge[i].value);也比较好理解。

树形DP-----HDU4003 Find Metal Mineral的更多相关文章

  1. 【树形dp】Find Metal Mineral

    [HDU4003]Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (J ...

  2. HDU4003 Find Metal Mineral 树形DP

    Find Metal Mineral Problem Description Humans have discovered a kind of new metal mineral on Mars wh ...

  3. HDU-4003 Find Metal Mineral 树形DP (好题)

    题意:给出n个点的一棵树,有k个机器人,机器人从根节点rt出发,问访问完整棵树(每个点至少访问一次)的最小代价(即所有机器人路程总和),机器人可以在任何点停下. 解法:这道题还是比较明显的能看出来是树 ...

  4. HDU4003 Find Metal Mineral

    看别人思路的 树形分组背包. 题意:给出结点数n,起点s,机器人数k,然后n-1行给出相互连接的两个点,还有这条路线的价值,要求最小花费 思路:这是我从别人博客里找到的解释,因为很详细就引用了 dp[ ...

  5. HDU-4003 Find Metal Mineral (树形DP+分组背包)

    题目大意:用m个机器人去遍历有n个节点的有根树,边权代表一个机器人通过这条边的代价,求最小代价. 题目分析:定义状态dp(root,k)表示最终遍历完成后以root为根节点的子树中有k个机器人时产生的 ...

  6. HDU4003Find Metal Mineral[树形DP 分组背包]

    Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Other ...

  7. hdu 4003 Find Metal Mineral 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...

  8. hdu 4003 Find Metal Mineral 树形dp ,*****

    Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Other ...

  9. HDU 4003 Find Metal Mineral(分组背包+树形DP)

    题目链接 很棒的一个树形DP.学的太渣了. #include <cstdio> #include <string> #include <cstring> #incl ...

  10. hdu4003详解(树形dp+多组背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Find Metal Mineral Time Limit: 2000/1000 MS (Jav ...

随机推荐

  1. UOJ #188 Sanrd —— min_25筛

    题目:http://uoj.ac/problem/188 参考博客:https://www.cnblogs.com/cjoieryl/p/10149748.html 关键是枚举最小质因子...所以构造 ...

  2. Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 1) C. Bear and Drawing

    题目链接:http://codeforces.com/contest/573/problem/C题目大意:在两行无限长的点列上面画n个点以及n-1条边使得构成一棵树,并且要求边都在同一平面上且除了节点 ...

  3. 程序或-内存区域分配& ELF分析 ***

    一.在学习之前我们先看看ELF文件. ELF分为三种类型: 1. .o 可重定位文件(relocalble file) 2. 可执行文件 3. 共享库(shared library) 三种格式基本上从 ...

  4. MongoDB 4.X搭建

    一.MongoDB4.X搭建 1.下载mongdb安装包,在官网上找到对应的版本,我的是centos7 找到上面的连接,通过命令行: 2.将下载的mongodb-linux-x86_64-4.0.0. ...

  5. thinkphp中的dump方法

    感受一下,调试. 1.print_r() 2.var_dump() 3.再看看thinkphp中的dump方法 清晰多了!真实够傻的,今天才发现有这么好的调试方法.

  6. php中的continue用法

    continue 2 表示跳出两层 continue 默认跳出一层 if (count($content_arr) > 0 ) { // 获取相应的goods数据 $goodsdata = ar ...

  7. maven学习2

    pom.xml文件中的内 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns= ...

  8. 01Javascript简介

    01 - Javascript 简介 web前端有三层: HTML:从语义的角度, 描述页面结构 CSS: 从审美的角度,描述样式(美化页面) JavaScript: 从交互的角度 , 描述行为(提升 ...

  9. xUtils怎么post请求上传json数据

    InfoSmallCodeBinding smallCode = new InfoSmallCodeBinding(); smallCode.setSmallCode("测试"); ...

  10. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...