博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 1561 The more, The Better (树形背包dp)
阅读量:4072 次
发布时间:2019-05-25

本文共 1996 字,大约阅读时间需要 6 分钟。

本文出自   

题目链接:  

题目

ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?

思路

简单树形背包dp,当作树形背包的第一道入门题非常合适

题目给的是森林,那么给增加一个"根节点", 指向森林中的每个树的根节点

f(i, j)表示子树i, 取j个城堡宝藏的时候的最大值
i的每个子节点表示的子树可以看作是一组物品,在这个子树上可以选择取1,2,3...j-1个的城堡宝藏
那么就是等价于对每个子节点做分组背包.
f(i, j) = max{ max{f(i, j-k)+f(v, k) | 1<=k<j }  |  v是i的子树  }
因为增加了一个根节点,而且拿子节点之前必须先拿父节点,所以m值要增加1,用来拿根节点.
有个优化, 对于某个子树,它取的个数不可能超过这个子树的节点数,优化了可以到0MS

代码

/**===================================================== *   This is a solution for ACM/ICPC problem * *   @source      : hdu-1561 The more, The Better *   @description : 树形背包dp *   @author      : shuangde *   @blog        : blog.csdn.net/shuangde800 *   @email       : zengshuangde@gmail.com *   Copyright (C) 2013/08/20 11:27 All rights reserved.  *======================================================*/#include        #include          #include            #include              #include                 #include                   #include                     #define MP make_pair using namespace std; typedef pair                     PII; typedef long long int64; const int INF = 0x3f3f3f3f; const double PI = acos(-1.0); const int MAXN = 210; vector                       adj[MAXN]; int val[MAXN]; int tot[MAXN]; int f[MAXN][MAXN]; int n, m; int dfs(int u) { f[u][1] = val[u]; tot[u] = 1; for (int i = 0; i < adj[u].size(); ++i) { int v = adj[u][i]; tot[u] += dfs(v); } for (int i = 0; i < adj[u].size(); ++i) { int v = adj[u][i]; for (int s = tot[u]>m?m:tot[u]; s >= 1; --s) { for (int j = 1; j < s && j <= tot[v]; ++j) { f[u][s] = max(f[u][s], f[u][s-j] + f[v][j]); } } } return tot[u]; } int main(){ while (~scanf("%d %d", &n, &m) && n + m) { // init for (int i = 0; i <= n; ++i) adj[i].clear(); val[0] = 0; for (int i = 1; i <= n; ++i) { int a; scanf("%d %d", &a, &val[i]); if (a) { adj[a].push_back(i); } else { adj[0].push_back(i); } } memset(f, 0, sizeof(f)); ++m; dfs(0); printf("%d\n", f[0][m]); } return 0; }

你可能感兴趣的文章
关于按钮的mouseOver和rollOver
查看>>
《多线程服务器的适用场合》例释与答疑
查看>>
Netty框架
查看>>
一个另类的swapChildren的实现
查看>>
用Eclipse平台进行c/c++开发
查看>>
启用解块
查看>>
Flash Player10 3D测试
查看>>
浅谈网络游戏项目开发难度
查看>>
flash fps游戏 fps多少为佳
查看>>
心得:对AMF3的误解
查看>>
事件对象的target和currentTarget属性区别
查看>>
事件冒泡阻止event.stopPropagation()
查看>>
Flex4 beta 的 Spark 布局
查看>>
Spark 架构和组件集的简要概述
查看>>
关于flex4中文(zh_CN)本地化应用编译不通过的解决方法
查看>>
摩斯密码表
查看>>
一段摩斯密码里的爱情故事
查看>>
游戏测试的技术难点和测试技术
查看>>
线程简介
查看>>
线程挂起自己,让出CPU
查看>>