HDU1561 The more, The Better
HDU1561 The more, The Better
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8490 Accepted Submission(s): 4964
Problem Description
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
Input
每个测试实例首先包括2个整数,N,M.(1 <= M <= N <=
200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。
Output
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
Sample Input
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
Sample Output
5
13
Author
8600
Source
HDU 2006-12 Programming Contest
Recommend
LL | We
have carefully selected several similar problems for you: 1011 2159 2639 1203 2602
分析:
典型的树形dp的题目。
首先,限制条件是选择m个物品,而每个物品最多选一次,跟0-1背包的区别在于有依赖关系,那么这层依赖关系我们可以借助于一个树来解决。借助dfs,从根节点开始dfs,然后直到叶子节点,回朔的时候进行0-1背包dp。
|
dp[i][j]表示以i为根节点取j个节点(包括根)的最优值 |
|||
|
map[i][j]表示i号节点的第j个孩子是什么 |
|||
|
num[i]表示i号节点的孩子数 |
|||
|
vis[i]==0表示i号节点没有被访问 |
|||

dp[i][j]=max(dp[i][j],dp[i][k]+dp[i的某个孩子节点][j-k])
表示在父亲节点i中选k个点和在i的某个孩子中选j-k个点
我们可以知道dp[i][1]=val[i],因为选一个点的话必须选自己 = =
依赖关系形成森林,要先把树转换成森林才能进行树形DP
增加一个根节点0即可
答案即为dp[0][m+1]:因为增加了一个根节点

#include<stdio.h>
#include<string.h>
int n,m;
int num[];
int map[][];
int dp[][];
bool vis[];
int max(int a,int b){
return a>b?a:b;
}
void dfs(int p)
{
int i,j,k;
//将p的访问置为true
vis[p]=true;
//遍历p的所有孩子
for(i=;i<=num[p];i++)
{
//t是节点p的第i个孩子
int t=map[p][i];
//如果t没被访问,dfs它
if(!vis[t]) dfs(t);
//m反向过来是保证后面的数据不影响前面的,比如当m=5时,j=m,k=2时,等式右边出现过一次dp[p][2]
//而当m=5时,j=2,k=2时, 状态转移方程等式左边出现了dp[p][2],显然,这个出现的dp[p][2]不能影响右边那个dp[p][2]
for(j=m;j>=;j--)//选择1个的状态不用更新了,就是节点本身,初始化中已经做了
{
for(k=;k<j;k++)//k表示父亲需要取的点的个数,j-k表示孩子需要取的点的个数
{
//如果有值
if(dp[t][j-k]!=-&&dp[p][k]!=-)
dp[p][j]=max(dp[p][j],dp[p][k]+dp[t][j-k]);
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m),n||m)
{
int a,b;
dp[][]=;
memset(num,,sizeof(num));
for(i=;i<=n;i++){
scanf("%d%d",&a,&b);
//初始化
dp[i][]=b;
map[a][++num[a]]=i;
}
m++;//增加一个点,森林转换成树
//初始化
for(i=;i<=n;i++){
dp[i][]=;vis[i]=;
for(j=;j<=m;j++){
dp[i][j]=-;
}
}
dfs();
printf("%d\n",dp[][m]);
}
return ;
}
没过的代码:

错误:第30行的g[a][++num[a]]=i;这里写成了g[a][++num[i]]=i;
#include <bits/stdc++.h>
const int N=2e2+;
using namespace std;
int dp[N][N],m,n;
int num[N],g[N][N];
bool vis[N]; void dfs(int r){
vis[r]=true;
for(int i=;i<=num[r];i++){
int v=g[r][i];
if(!vis[v]) dfs(v);
for(int j=m;j>=;j--){
for(int k=;k<j;k++){
//这里可以判断一下如果有值的话
if(dp[r][k]!=-&&dp[v][j-k]!=-)
dp[r][j]=max(dp[r][j],dp[r][k]+dp[v][j-k]);
}
}
}
} int main(){
freopen("in.txt","r",stdin);
memset(dp,-,sizeof(dp));
while(scanf("%d %d",&n,&m),n||m){
for(int i=;i<=n;i++){
int a,w;
cin>>a>>w;
g[a][++num[a]]=i;//存孩子 //这里写成了g[a][++num[i]]=i;
dp[i][]=w;
dp[i][]=;
}
dp[][]=;
dp[][]=;
m++;
dfs();
cout<<dp[][m]<<endl;
} return ;
}
HDU1561 The more, The Better的更多相关文章
- 【树形dp小练】HDU1520 HDU2196 HDU1561 HDU3534
[树形dp]就是在树上做的一些dp之类的递推,由于一般须要递归处理.因此平庸情况的处理可能须要理清思路.昨晚開始切了4题,作为入门训练.题目都很easy.可是似乎做起来都还口以- hdu1520 An ...
- hiho1055/hdu1561 - 树形dp转换成背包
题目链接 输入:一棵树,每个节点一个权值. 输出:包括1号节点在内的m个节点组成的连通分量的权值和的最大值 hdu1561和hiho1055一样,只是变换了下说法 /***************** ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- hdu1561 树形dp + 背包
#include<cstdio> #include<cstring> #include<iostream> #define INF 999999999 using ...
- HDU1561 The more, The Better(树形DP)
题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏. 题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP: ...
- HDU-1561 The more, The Better (树形DP+分组背包)
题目大意:给出一片森林,总共有n个点,并且都有权值.从中选出m个,使权值和最大.其中,选某个节点之前必须先选其父节点. 题目分析:给所有的树都加一个共同的权值为0的根节点,使森林变成一棵树.定义状态d ...
- 树形dp hdu1561
有的堡垒攻克需要攻克另一个堡垒,形成一个森林,最多攻克m个堡垒,求获得宝物的最大价值. 1,以0做根将森林形成树: 2,用背包计算当前节点下需要攻克k个堡垒能获得的宝物最大价值,但是注意同一个根节点的 ...
- hdu1561(树形dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 题意:n座城堡,每个里面都有宝物,要求在你可以攻占m个城堡得到的最多的宝物,但是如果要攻破一个城 ...
- hdu1561(树形背包)
给定n,m表示n个城堡,我们可以选择攻占m个城堡.要使得价值最大 接下来n行 a b, 第i行的a b,表示攻占第i个城堡的价值为b,但需要先攻占第a个城堡 如果有多个a=0的点,那么就不是一棵树 ...
随机推荐
- 讲究地使用 List
本篇旨意在于讨论List的基本用法,不做全面讲解,仅仅涉及构造函数List.Add.RemoveAt 先看看这几个函数的代码 1.构造函数 static readonly T[] _emptyArra ...
- Mybatis与Hibernate的对比
Mybatis与Hibernate的对比 工作中,用了一段Hibernate与Mybatis,也在此简单的聊上几句,希望对大家有帮助. Mybatis与Hibernate不同,它不完全是一个ORM框架 ...
- halcon 模板匹配 -- create_shape_model
create_shape_model(Template : : //reduce_domain后的模板图像 NumLevels,//金字塔的层数,可设为“auto”或0—10的整数 AngleStar ...
- sql server 游标fetch简单用法
//遍历tmp_check的年份和月份 DECLARE @year ) DECLARE @month ) DECLARE cur CURSOR FOR SELECT nf,yf FROM tmp_ch ...
- Can't find variable: SockJS vue项目
用的vue-cli(webpack-simple模板),在开发环境运行(npm run dev),一直都没有问题,突然在ios的safari中调试,出现报错:Can't find variable: ...
- esp32使iOS 获取蓝牙外设的Mac地址
最近在做一个需要上下位机的项目,我负责的任务下位机,使用的主控芯片是esp32.这个项目中有一项是需要手机扫描二维码然后连接作为esp32的蓝牙.二维码中包含了mac地址信息,在手机扫描周围设备的时候 ...
- 【剑指Offer】6、旋转数组的最小数字
题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5 ...
- 接口测试与Postman
阅读目录 1.接口测试简介 1.1 什么是接口测试 1.2 接口测试的必要性 1.3 接口测试流程 1.4 接口文档 1.5 接口测试用例设计 1.6 接口测试用例模板 2.Postman 2.1 ...
- 洛谷P1478 陶陶摘苹果(升级版)【水题】
又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同的是:陶陶之前搬凳子,力气只剩下s ...
- 单个图片获取-爬取网易"数读"信息数据(暴涨的房租,正在摧毁中国年轻人的生活)
参考链接:https://www.makcyun.top/web_scraping_withpython3.html 该网页其实有16张图片,但是因为页面数据中某处多个空白,导致参考链接中的方式只有1 ...