HDU 4003 Find Metal Mineral(树形dp + 分组背包)
2017-01-19 09:55
363 查看
题意:给你n个点,n - 1条边,k个机器人,s为起点,问遍历所有点的最小花费。
————————————————————————————————————————————————
【转载】:
dp[i][j]表示对于以i结点为根结点的子树,放j个机器人所需要的权值和。
当j=0时表示放了一个机器人下去,遍历完结点后又回到i结点了。状态转移方程类似背包
如果最终的状态中以i为根结点的树中有j(j>0)个机器人,那么不可能有别的机器人r到了这棵树后又跑到别的树中去
因为那样的话,一定会比j中的某一个到达i后跑与r相同的路径再回到i,再接着跑它的路径要差(多了一条i回去的边)
这样的话,如果最后以i为根结点的树中没有机器人,那么只可能是派一个机器人下去遍历完后再回来
————————————————————————————————————————————————
此题还用到了分组背包的思想附上分组背包的伪代码,详细可去看一下背包九讲
使用一维数组的“分组背包”伪代码如下:
for 所有的组i
for v=V..0
for 所有的k属于组i
f[v]=max{f[v],f[v-c[k]]+w[k]}
思路:对于每一个结点运用一次分组背包,假如i有n个儿子,每个儿子是一个分组,分组里的选项有dp[son][0],dp[son][1]........dp[s
9089
on][k],跟分组背包又不同的一点是每个分组都必需选一项,所以我们可以事先将dp[son][0]加到dp[i][k]上,通过dp看是否有比这更优解。
附上ac代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#define For0(n) for(int i = 0; i < n; i++)
#define For1(n) for(int i = 1; i <= n; i++)
#define Forn_m(n,m) for(int i = n; i <= m; i++)
#define MAX 10120
using namespace std;
struct Edge
{
int to, length;
};
vector <Edge> vec[MAX];
int n, s, k;
int dp[MAX][12];
bool vis[MAX];
void dfs(int root)
{
int num = vec[root].size();
vis[root] = true;
For0(num)
{
if (vis[vec[root][i].to])
continue;
dfs(vec[root][i].to);
for (int x = k; x >= 0; x--)
{
dp[root][x] += dp[vec[root][i].to][0] + 2*vec[root][i].length;
for (int y = 1; y <= x; y++)
dp[root][x] = min(dp[root][x], dp[root][x - y]
+ dp[vec[root][i].to][y] + y * vec[root][i].length);
}
}
}
int main()
{
int u, v;
Edge temp;
while (scanf("%d%d%d", &n, &s, &k) != EOF)
{
memset(vis, 0, sizeof(vis));
memset(dp, 0, sizeof(dp));
For0(MAX)
vec[i].clear();
Forn_m(2, n)
{
scanf("%d%d%d", &u, &temp.to, &temp.length);
vec[u].push_back(temp);
v = temp.to;
temp.to = u;
u = v;
vec[u].push_back(temp);
}
dfs(s);
printf("%d\n", dp[s][k]);
}
return 0;
}
————————————————————————————————————————————————
【转载】:
dp[i][j]表示对于以i结点为根结点的子树,放j个机器人所需要的权值和。
当j=0时表示放了一个机器人下去,遍历完结点后又回到i结点了。状态转移方程类似背包
如果最终的状态中以i为根结点的树中有j(j>0)个机器人,那么不可能有别的机器人r到了这棵树后又跑到别的树中去
因为那样的话,一定会比j中的某一个到达i后跑与r相同的路径再回到i,再接着跑它的路径要差(多了一条i回去的边)
这样的话,如果最后以i为根结点的树中没有机器人,那么只可能是派一个机器人下去遍历完后再回来
————————————————————————————————————————————————
此题还用到了分组背包的思想附上分组背包的伪代码,详细可去看一下背包九讲
使用一维数组的“分组背包”伪代码如下:
for 所有的组i
for v=V..0
for 所有的k属于组i
f[v]=max{f[v],f[v-c[k]]+w[k]}
思路:对于每一个结点运用一次分组背包,假如i有n个儿子,每个儿子是一个分组,分组里的选项有dp[son][0],dp[son][1]........dp[s
9089
on][k],跟分组背包又不同的一点是每个分组都必需选一项,所以我们可以事先将dp[son][0]加到dp[i][k]上,通过dp看是否有比这更优解。
附上ac代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#define For0(n) for(int i = 0; i < n; i++)
#define For1(n) for(int i = 1; i <= n; i++)
#define Forn_m(n,m) for(int i = n; i <= m; i++)
#define MAX 10120
using namespace std;
struct Edge
{
int to, length;
};
vector <Edge> vec[MAX];
int n, s, k;
int dp[MAX][12];
bool vis[MAX];
void dfs(int root)
{
int num = vec[root].size();
vis[root] = true;
For0(num)
{
if (vis[vec[root][i].to])
continue;
dfs(vec[root][i].to);
for (int x = k; x >= 0; x--)
{
dp[root][x] += dp[vec[root][i].to][0] + 2*vec[root][i].length;
for (int y = 1; y <= x; y++)
dp[root][x] = min(dp[root][x], dp[root][x - y]
+ dp[vec[root][i].to][y] + y * vec[root][i].length);
}
}
}
int main()
{
int u, v;
Edge temp;
while (scanf("%d%d%d", &n, &s, &k) != EOF)
{
memset(vis, 0, sizeof(vis));
memset(dp, 0, sizeof(dp));
For0(MAX)
vec[i].clear();
Forn_m(2, n)
{
scanf("%d%d%d", &u, &temp.to, &temp.length);
vec[u].push_back(temp);
v = temp.to;
temp.to = u;
u = v;
vec[u].push_back(temp);
}
dfs(s);
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
- 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)
- HDU 4003 Find Metal Mineral(树形dp,从根节点出发k个机器人遍历所有边的最小代价和)
- HDU 4003 Find Metal Mineral 树形DP
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)