UVA Live Archive 4015 Cave (树形dp,分组背包)
和Heroes Of Might And Magic 相似,题目的询问是dp的一个副产物。
距离是不好表示成状态的,但是可以换一个角度想,如果知道了从一个点向子树走k个结点的最短距离,
那么就可以回答走x距离能访问到的最大结点数量。
当访问了一棵子树,想要访问子树外的结点时,一定要先从子树的根结点出来。
状态可以定义为dp[u][k][?],u表示根节点,k表示访问u的k个子结点,?的取值为0和1表示 不回到u 和 回到u。
不难想到转移过程:
dp[u][k][0] <- dp[u][a][1] + dp[v][b][0] 或 dp[v][b][1] + dp[u][a][0]
dp[u][k][1] <- dp[u][a][1] + dp[v][b][1]
k = a+b+1, v 是 u的子节点
边界为 dp[u][0][0] = dp[u][0][1] = 0表示停留在u.
困难的是转移的顺序,必须保证重复走一个结点只算一次,
实际计算的时候我们只能一个一个的枚举v,对于枚举到v的结点数量b只能从没有考虑过v结点的状态转移。
把结点数量看出物品,v的结点数实际上是一组物品,不能同时选。
剩下和分组背包差不多。
#include<bits/stdc++.h>
using namespace std; #define PS push const int maxn = ;
const int INF = 0x3f3f3f3f; int hd[maxn], nx[maxn], to[maxn], ec;
void add(int u,int v)
{
to[ec] = v;
nx[ec] = hd[u];
hd[u] = ec++;
} int fa[maxn], dist[maxn], deg[maxn], sz[maxn];
int ks;
int n; int dp[maxn][][maxn]; int sol()
{
queue<int> q;
for(int i = ; i < n; i++){
if(!deg[i]) { q.PS(i); }
}
int u;
while(q.size()){
u = q.front(); q.pop();
sz[u] = ;
dp[u][][] = dp[u][][] = ;
for(int i = hd[u]; ~i; i = nx[i]){
int v = to[i];
sz[u] += sz[v];
for(int k = sz[u]-sz[v]; k < sz[u]; k++) dp[u][][k] = dp[u][][k] = INF;
for(int k = sz[u]-; k > ; k--){//从大到小枚举k 保证是上一组的状态转移过来
for(int a = min(sz[v],k)-; a >= ; a--){//先枚举k,然后枚举物品保证组内物品不会同时选到
int b = k--a;
//知道dp[v][b][0] 和 dp[v][b][1] 以后新增加的路径
dp[u][][k] = min(dp[u][][k],min(dp[u][][b]+dp[v][][a]+dist[v],dp[u][][b]+dp[v][][a])+dist[v]);
dp[u][][k] = min(dp[u][][k],dp[u][][b]+dp[v][][a]+dist[v]*);
}
}
}
if(!--deg[fa[u]]) q.PS(fa[u]);//fa[root]虽然不确定,但是在0~500内且deg = 0
}
return u;
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
while(scanf("%d",&n),n){
memset(deg,,sizeof(deg));
memset(hd,-,sizeof(hd)); ec = ;
for(int i = ; i < n; i++){
int u,f,d; scanf("%d%d%d",&u,&f,&d);
fa[u] = f; dist[u] = d;
add(f,u); deg[f]++;
}
printf("Case %d:\n",++ks);
int *ans = dp[sol()][];
int Q; scanf("%d",&Q);
while(Q--){
int x; scanf("%d",&x);
printf("%d\n",upper_bound(ans,ans+n,x)-ans);//能走的最大子结点数+1
}
}
return ;
}
UVA Live Archive 4015 Cave (树形dp,分组背包)的更多相关文章
- HDU4003Find Metal Mineral[树形DP 分组背包]
Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Other ...
- HDU-1011 Starship Troopers (树形DP+分组背包)
题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<i ...
- Ural-1018 Binary Apple Tree(树形dp+分组背包)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #i ...
- 【P2015】二叉苹果树 (树形DP分组背包)
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 现在这颗树枝条太多了,需要剪枝.但是 ...
- hdu 1561 树形dp+分组背包
题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m) ...
- poj2486 Apple Tree (树形dp+分组背包)
题目链接:https://vjudge.net/problem/POJ-2486 题意:一棵点权树,起点在1,求最多经过m条边的最大点权和. 思路: 树形dp经典题.用3维状态,dp[u][j][0/ ...
- hdu1561 The more, The Better 树形DP+分组背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 思路: 典型的树形背包题目: 定义dp[i][j]表示以i为根节点,攻打j个城堡的获得的财宝的最 ...
- hdu 4003 树形dp+分组背包 2011大连赛区网络赛C
题意:求K个机器人从同一点出发,遍历所有点所需的最小花费 链接:点我 Sample Input 3 1 1 //3个点,从1出发,1个机器人 1 2 1 1 3 1 3 1 2 1 2 1 1 3 1 ...
- HDU-4003 Find Metal Mineral (树形DP+分组背包)
题目大意:用m个机器人去遍历有n个节点的有根树,边权代表一个机器人通过这条边的代价,求最小代价. 题目分析:定义状态dp(root,k)表示最终遍历完成后以root为根节点的子树中有k个机器人时产生的 ...
随机推荐
- 【转】如何解决C盘根目录无法创建或写入文件
源地址:http://blog.csdn.net/xinke453/article/details/7496545
- 初识Scrapy之再续火影情缘
前言Scrapy框架之初窥门径1 Scrapy简介2 Scrapy安装3 Scrapy基础31 创建项目32 Shell分析4 Scrapy程序编写41 Spiders程序测试42 Items编写43 ...
- ffmpeg转码多路输出(二)
ffmpeg转码多路输出(二)本程序支持一路输入多路输出,可根据map配置自行添加,第1路为纯拷贝,其他2路经过编解码,格式转换缩放和重采样,纯拷贝方面不同格式适应方面还没做全,以后补充.本程序适合多 ...
- idea长用快捷键
1CA(ctrl+alt) 1.1(记忆mlv) ctrl alt m 代码封装成方法 ctrl alt L格式化代码 ctrl alt v补全返回值 (eclipse: alt shift l) 1 ...
- Linux--7
一.Nginx.conf主配置文件 Nginx主配置文件conf/nginx.conf是一个纯文本类型的文件,整个配置文件是以区块的形式组织的.一般,每个区块以一对大括号{}来表示开始与结束. 核心模 ...
- mysql /etc/my.cnf
[client] port=3306 socket = /tmp/mysql.sock default-character-set=utf8 [mysqld] # 1 general config p ...
- 01.Spring Ioc 容器
基本概念 Spring 的 Ioc 容器,通常也称应用上下文.它包含了两个概念 Ioc 和 容器: 容器:顾名思义就是用来装东西的,在 Spring 中容器里盛放的就是各种各样的 Bean.既然装了东 ...
- poj(3080)
题目链接:http://poj.org/problem?id=3080 学习博客:https://www.cnblogs.com/acjiumeng/p/6818213.html Blue Jeans ...
- Spark Mllib里的如何对单个数据集用斯皮尔曼计算相关系数
不多说,直接上干货! import org.apache.spark.mllib.stat.Statistics 具体,见 Spark Mllib机器学习实战的第4章 Mllib基本数据类型和Mlli ...
- 【密码学】DES、3DES
文章1: 这一篇文章要解决数据加密——数据补位的问题.DES算法的两种模式ECB和CBC问题以及更加安全的算法——3DES算法. 一.数据补位 DES数据加解密就是将数据按照8个字节一段进行DES加密 ...