hdu 4003 Find Metal Mineral(树形dp+分组背包)
来源:互联网 发布:使用c语言完成http请求 编辑:程序博客网 时间:2024/03/29 12:43
Find Metal Mineral
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4003
解题思路:
题目大意:
给你一棵n个节点的树, 节点编号为1~n, 每条边都有一个花费值。有k个机器人从S点出发, 问让机器人遍历所有边,最少花费值多少?
算法思想:
根据题意可以知道,机器人是可以走回头路的。所以分析下可知,如果从根节点派往子节点如果要折回到根节点,派向这个子节点
的机器人越多,产生的重复路径就会越多,所以那么派往这个子节点的个数为1时是最优策略。那么定义dp[i][0]存放1个机器人,从
子节点返回到根节点的花费。
现在思考:如果根节点s, 有 n个子节点,那么要怎么样选择才能使dp[s][k]的值最小呢?
⑴当机器人的个数为1时,那么只有一种方法,就是用这一个机器人跑遍每个子节点、也就是每次机器人都要从一个子节点返回根节
点,然后走向另一个节点,直到遍历所有点为止。那么这种状态下的状态转移为: dp[s][0]=dp[next][0]+2*w; (其中s为根节点,
next为子节点,w为s到next的权值)。
⑵当机器人的个数>1时,那么必然存在机器人不必返回根节点的策略。同时由⑴也可以求出折回根节点的花费。
那么求根节点s下的n个子节点,把每个节点看做一个整体,定义dp(n,j)为前n个节点派j个机器人的最小花费,其实就是个包,dp(n,j)
与dp(n-1,j)必然存在某种联系。可以推出dp(n,j)=min(dp(n,j), dp(n-1,j-k)+dp[v][k]+k*w); (1<=k<=j,w为s到当前这个子节点v的权值),
因为只要用到上一个子节点的状态。所以对起始点s的所有子节点扫描一遍就可以了。
AC代码:
#include <bits/stdc++.h>using namespace std;const int maxn = 10005;struct node{ int v,w; node(int _v,int _w):v(_v),w(_w){}};vector<node> path[maxn];int dp[maxn][15];//节点i,向子节点放j个机器人的最小花费int n,s,k;void dfs(int u,int father){ int len = path[u].size(); for(int i = 0; i < len; i++){ int next = path[u][i].v; int w = path[u][i].w; if(father == next) continue; //如果当前的节点为父亲节点,不往下走。 if(father == -1 || father != next){//如果u为s点 (最上面的那个根节点)或者next不等于父亲节点 //cout<<next<<" "<<u<<endl, dfs(next,u); } //cout<<next<<endl; for(int j = k; j >= 1; j--){ dp[u][j] += dp[next][0] + 2*w; for(int jj = 1; jj <= j; jj++) dp[u][j] = min(dp[u][j],dp[u][j-jj]+dp[next][jj]+jj*w); } dp[u][0] += dp[next][0] + 2*w; }}int main(){ while(~scanf("%d%d%d",&n,&s,&k)){ for(int i = 0; i <= 10000; i++) path[i].clear(); memset(dp,0,sizeof(dp)); int u,v,w; for(int i = 0; i < n-1; i++){ scanf("%d%d%d",&u,&v,&w); path[u].push_back(node(v,w)); path[v].push_back(node(u,w)); } dfs(s,-1); printf("%d\n",dp[s][k]); } return 0;}
- hdu 4003 Find Metal Mineral(树形DP+分组背包)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- hdu 4003 Find Metal Mineral (树形dp+分组背包)
- hdu 4003 Find Metal Mineral 【树形dp,分组背包】
- hdu 4003 Find Metal Mineral 树形dp+分组背包
- HDU 4003 Find Metal Mineral(树形dp + 分组背包)
- HDU 4003 Find Metal Mineral (树形DP+分组背包)
- (中等) 树形分组背包 HDU 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral(树形DP+分组背包,每个物品必须只能选一次)
- hdu 4003 Find Metal Mineral (树形背包dp)
- hdu 4003 Find Metal Mineral (树形dp+背包)
- HDU 4003 Find Metal Mineral【经典树形DP背包】
- HDU 4003 Find Metal Mineral 树形DP
- hdu 4003 Find Metal Mineral 树形DP
- HDU-4003 Find Metal Mineral 树形dp
- HDU4003 Find Metal Mineral(树形DP+分组背包)
- HDU 4003--Find Metal Mineral(树形dp)
- C语言实现封装、继承和多态
- FrameLayout
- cocos2dx和quick的区别
- Android开发之WebService介绍
- Change Queue Not Work In Unity Shader
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- swift中实现description
- 关于VC中 error C2871: 'std' : does not exist or is not a namespace
- 2016蓝桥杯假期任务之《泊松汾酒》
- C#上机实验(三)
- EasyUI - datagrid属性idField详解
- Linux中常用操作命令
- 重写 strlen
- Android Light开发(一)