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. 几个ssh和sftp的命令

    sudo apt-get install openssh-server 装server sudo /etc/init.d/ssh stop sudo /etc/init.d/ssh start sud ...

  2. 根据wsdl文件生成WebService客户端代码

    有时候在项目中,一个项目可能有好几个公司在做.系统之间难免会出现互相调用接口的现象,这时候有一种办法就是使用webService.本篇文章将介绍如何将对接系统提供的WebService接口,根据对方提 ...

  3. vue参考

    https://github.com/taylorchen709/vue-admin http://element-cn.eleme.io/#/zh-CN/component/layout https ...

  4. go语言学习杂记

    go语言在windows下下载安装 推荐在golang中国下载 http://www.golangtc.com/download 安装.... go环境变量与工作目录 根据约定GOPATH需要建立3个 ...

  5. 【转】Jmeter参数化

    参数化:简单的来理解一下,我们录制了一个脚本,这个脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户来登录系统. 这个时候就需要对用户名和密码进 ...

  6. codeforce 985C Liebig's Barrels(贪心+思维)

    Liebig's Barrels time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  7. Tarjan模版(链式向前星表示方法)

    这道模版用到了链式向前星表示法: struct node { int v,next; }edge[]; void add(int x,int y) { edge[++cnt].next=heads[x ...

  8. Java-API-Package:java.net百科

    ylbtech-Java-API-Package:java.net百科 并非所有系统都支持 IPv6 协议,而当 Java 网络连接堆栈尝试检测它并在可用时透明地使用它时,还可以利用系统属性禁用它.在 ...

  9. Linux - 归档和压缩

    归档 归档就是将多个文件或目录合并成一个文件 归档的目的就是方便备份.还原及文件的传输操作 tar 命令:将多个文件或目录归档到一个文件中,可以根据需要只还原归档文件中的某些指定的文件 c:创建,v: ...

  10. 二进制(signed or unsigned)补码

    在计算机系统中,数值一律用补码来表示(存储). 主要原因:使用补码,可以将符号位和其它位统一处理:同时,减法也可按加法来处理.另外,两个用补 码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃 ...