hdu1561 The more, The Better 树形DP+分组背包
2024-09-23 19:56:06
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561
思路:
典型的树形背包题目:
定义dp[i][j]表示以i为根节点,攻打j个城堡的获得的财宝的最优值,那么dp[i][j]=max(dp[i][j],dp[son][k]+dp[i][j-k]) 其中son为i的儿子
然后从叶子节点往上进行背包即可
刚接触的同学会有疑问:就是不知道怎样将题目中的数据建为一个树,其实很简单,只要把0作为根结点即可 0节点的value初始化为0
然后dp[0][m+1]即为求得的答案,是不是很简单啊。。。。
注意初始化。
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define MAX 210
int dp[MAX][MAX];
vector<int>v[MAX];
int vis[MAX];
int m,n;
void init()
{
memset(dp,-,sizeof(dp));
memset(vis,,sizeof(vis));
for(int i=;i<MAX;i++) v[i].clear();
}
void dfs(int root)
{
vis[root]=;
for(int i=;i<v[root].size();i++)
{
if(vis[v[root][i]]) continue;
int son=v[root][i];
dfs(son); for(int i=m;i>=;i--)
for(int j=;j<i;j++)
if(dp[root][i-j]!=-&&dp[son][j]!=-)
dp[root][i]=max(dp[root][i],dp[son][j]+dp[root][i-j]);
} }
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
if(n==&&m==) break;
for(int i=;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
v[a].push_back(i);
dp[i][]=b;
dp[i][]=;
}
m++;
dp[][]=;
dp[][]=;
dfs();
cout<<dp[][m]<<endl;
}
return ;
}
最新文章
- Redis集群案例与场景分析
- 【centOS】账号管理
- 关于flume配置加载(二)
- codevs1004四子连棋[BFS 哈希]
- 【BZOJ-3638&;3272&;3267&;3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广
- Linux 吃掉我的内存
- LINUX系统下添加映射存储LUN
- JS基础---->;js中ajax的使用
- 【转载】使用C#进行系统编程
- 雷兽的数据库CAP乱谈之(一)阐述
- 简易的JQuery设置Cookie
- netstat命令[转]
- 怎样提交FIREDAC数据集的DELTA到中间件然后保存进数据库
- emulator shortcut
- [Qt初级] 解决 中QMainWindow和QDockWidget添加布局失败问题
- AR入门系列-04-vuforia识别多个图片及同屏展示
- C# 委托与事件详解(三)
- LVS-DR集群搭建
- RelativeLayout中include 控件覆盖重叠的问题
- lambda 表达式拼接