HDU 4044 GeoDefense(动态规划)
GeoDefense
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 745 Accepted Submission(s): 307
The choice and positioning of the towers is the essential strategy of the game. Many games, such as Flash Element Tower Defense, feature enemies that run through a "maze", which allows the player to strategically place towers for optimal effectiveness. However,
some versions of the genre force the user to create the maze out of their own towers, such as Desktop Tower Defense. Some versions are a hybrid of these two types, with preset paths that can be modified to some extent by tower placement, or towers that can
be modified by path placement.
geoDefense is a Thinking Man’s Action Tower Defense. It has become one of "PC World's 10 iPhone Games You CANNOT Live Without". Using exciting vectorized graphics, this highly kinetic game brings a whole new dimension to the defense genre. Devastate creeps
with blasters, lasers and missiles and watch their energy debris swirl through the gravity wells of your vortex towers.
There is a geoDefense maze of n points numbered from 1 and connected by passageways. There are at least two dead ends among these n points, and there is always one and only one path between any pair of points. Point 1 is a dead end, and it’s the base of enemies,
and all the other dead ends are your bases.
To prevent the enemy reaching your bases, you have to construct towers to attack the enemy. You can build tower on any point and you can only build one tower on one point. A tower can only shot the enemy when it passes the tower. You are given ki choices to
build tower on point i, and each choice is given in the format of (price, power) which means that you can build a tower with attack power value equals power in the cost of price. You can also build nothing on a point so it will not cost your money. A tower
will reduce the enemy’s HP by its attack power. When the HP is less or equal to zero, the enemy dies immediately.
The base of enemies will release only one enemy. It moves very fast that you cannot do anything such as building towers while it is running. It runs all the way until it dies or reaches one of your bases. However, you cannot predict the route it will go through.
To win the game, you must kill the enemy before it reaches your bases. You have to strategically place towers for optimal effectiveness so that the fortifications are steady enough to protect the bold and powerful enemy with high HP. You are troubling your
head on figuring out the highest HP of the enemy you are able to kill on the way certainly. You have money m when the game begins.
Please note that the towers build in the enemy’s base or your bases are all effective and if the enemy is shot to death in your bases, you still win.
For each test case, the first line contains only one integer n (2 <= n <= 1000) meaning the number of points.
The following n-1 lines describe the passageways. Each line contains two integers u and v, which are the endpoints of a passageway.
The following line contains only one integer m (1 <= m <= 200) meaning the amount of your money when the game begins.
Then n lines follow. The ith line describes the construction choices of the ith point. It starts with an integer ki (0 <= ki <= 50) and ki is followed by ki pairs of integers separated by spaces. The jth pair is (pricei,j, poweri,j), 0 <= pricei,j <= 200, 0
<= poweri,j <= 50000. ki being zero means that you can’t build a tower on the ith point.
2
2
1 2
30
3 10 20 20 40 30 50
3 10 30 20 40 30 45
4
2 1
3 1
1 4
60
3 10 20 20 40 30 50
3 10 30 20 40 30 45
3 10 30 20 40 30 35
3 10 30 20 40 30 35
70
80
题目输入描述:
有T组测试数据,每组
首先一个n,表示一颗生成树有n个节点
接下来n-1行表示n-1条边描述这个生成树
接下来一行表示你的总的钱数sum
接下来n行,第i行表示树上的第i号节点可以建 ki 个 塔,每个塔两个数字参数表示花费和造成的伤害。
这是个塔防游戏,敌人从树根(1号节点)出发,叶子节点是你的基地,敌人的路线不固定,经过每个节点的塔后受到伤害
问你在总的花费下,你选择建一些塔,敌人的血量至多是多少才能保证不伤害到你的基地。
解题思路:
这题已经讨论过,用两个DP,也就是DP里面套一个DP,今天思维清晰,实现了,代码100行,超过了正常DP的长度。
有人用树形DP去实现,不管用什么实现,核心思路肯定相像。
(1)首先,可以把这整颗树看成一个问题,就是让这个树要求的那个答案ans最大。
要使 ans 最大,就可以分析一下,我认为ans可以分成两部分
第一部分:这个很简单,就是“树根”造塔产生的花费ci,造成的伤害pi
第二部分:
这个比较复杂,就是树根下有很多子树,也就是敌人可能走任意一条路,很明显敌人会走哪个伤害最小的路。
也就是在剩下的钱数下使得最小的路径的伤害值最大,假设以求出,记为DP2([son],left_money)
综合这个两个部分,所以这颗树的答案ans=DP1(root,sum) = max { pi + DP2([son],sum-ci) }
(2)那么 DP2([son],money)这个怎么求?
这个也很好求,枚举每个son的花费,在所有的花费的情况下求最大,但是儿子之间的伤害取最小。
也就是:DP2([son],money)=DP2(son1,money)
假设第一个儿子花了Ci元,得到的伤害是多少呢?很明显示DP1(son1,Ci)
所以DP2(son1,money)= max{ min( DP1(son1,Ci),DP(son2,money-Ci) ) }
综上,由(1)(2)两个DP可以求出答案也就是调用DP1(1,sum).
解题代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std; const int maxn=1100; vector <int> g[maxn],path[maxn];
vector < pair<int,int> > v[maxn];
int n,money,next[maxn];
int dp1[maxn][210],dp2[maxn][210],vis1[maxn][210],vis2[maxn][210],mark1,mark2; int DP1(int k,int sum); int DP2(int k,int sum){
if(k==-1) return (1<<30);
if(vis2[k][sum]==mark2) return dp2[k][sum];
int ans=0;
for(int i=0;i<=sum;i++){
int tmp=min(DP1(k,i),DP2(next[k],sum-i));
if(tmp>ans) ans=tmp;
}
vis2[k][sum]=mark2;
return dp2[k][sum]=ans;
} int DP1(int k,int sum){
if(vis1[k][sum]==mark1) return dp1[k][sum];
int ans=0;
for(int i=0;i<v[k].size();i++){
if(sum<v[k][i].first) continue;
int tmp=v[k][i].second;
if(g[k].size()>0) tmp+=DP2(g[k][0],sum-v[k][i].first);
if(tmp>ans) ans=tmp;
}
vis1[k][sum]=mark1;
return dp1[k][sum]=ans;
} void dfs(int u,int fa){
for(int i=0;i<path[u].size();i++){
if(path[u][i]!=fa){
g[u].push_back(path[u][i]);
dfs(path[u][i],u);
}
}
} void init(){
for(int i=0;i<=n;i++){
g[i].clear();
v[i].clear();
path[i].clear();
}
mark1++;
mark2++;
} void input(){
int x,y,q;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
path[x].push_back(y);
path[y].push_back(x);
}
scanf("%d",&money);
for(int i=1;i<=n;i++){
scanf("%d",&q);
v[i].push_back(make_pair(0,0));
while(q-- >0){
scanf("%d%d",&x,&y);
v[i].push_back(make_pair(x,y));
}
}
dfs(1,-1);
for(int i=1;i<=n;i++){
for(int j=1;j<g[i].size();j++){
next[g[i][j-1]]=g[i][j];
}
if(g[i].size()>0) next[g[i].back()]=-1;
}
} void solve(){
printf("%d\n",DP1(1,money));
} int main(){
int T;
scanf("%d",&T);
for(int t=0;t<T;t++){
scanf("%d",&n);
init();
input();
solve();
}
return 0;
}
版权声明:欢迎关注我的博客,本文为博主toyking原创文章,未经博主允许不得转载。
HDU 4044 GeoDefense(动态规划)的更多相关文章
- hdu 4044 GeoDefense (树形dp | 多叉树转二叉树)
题目链接:hdu-4044 题意 这是一个塔防游戏,地图是一个n个编号为1-n的节点的树, 节点1是敌人的基地,其他叶子节点都是你的基地. 敌人的基地会源源不断地出来怪兽,为了防止敌人攻进你的基 ...
- HDU 4044 GeoDefense
树形DP,和背包差不多.dp[now][x]表示now这个节点的子树上,花费为x的时候,获得的最大防御能力(保证敌方HP<=0) #include<cstdio> #include& ...
- HDU 4044 GeoDefense (树形DP,混合经典)
题意: 给一棵n个节点的树,点1为敌方基地,叶子结点都为我方阵地.我们可以在每个结点安放炸弹,每点至多放一个,每个结点有ki种炸弹可选,且每种炸弹有一个花费和一个攻击力(1点攻击力使敌人掉1点hp). ...
- hdu 4044 树形DP 炮台打怪 (好题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4044 题目大意:给定n个节点组成的树,1为敌方基地,叶子结点为我方结点.我们可以在每个结点安放炮台,至 ...
- [HDU 3535] AreYouBusy (动态规划 混合背包 值得做很多遍)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意:有n个任务集合,需要在T个时间单位内完成.每个任务集合有属性,属性为0的代表至少要完成1个 ...
- [HDU 1114] Piggy-Bank (动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114 简单完全背包,不多说. #include <cstdio> #include < ...
- [HDU 2955]Robberies (动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 题意是给你一个概率P,和N个银行 现在要去偷钱,在每个银行可以偷到m块钱,但是有p的概率被抓 问 ...
- HDU 2571 命运 动态规划
命运 http://acm.hdu.edu.cn/showproblem.php?pid=2571 Problem Description 穿过幽谷意味着离大魔王lemon已经无限接近了!可谁能想到, ...
- HDU 5481 Desiderium 动态规划
Desiderium Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=548 ...
随机推荐
- .Net魔法堂:史上最全的ActiveX开发教程——ActiveX与JS间交互篇
一.前言 经过上几篇的学习,现在我们已经掌握了ActiveX的整个开发过程,但要发挥ActiveX的真正威力,必须依靠JS.下面一起来学习吧! 二.JS调用ActiveX方法 只需在UserContr ...
- 查找表或其他对象在某个Server上的存在
EXEC sp_MSforeachdb 'use ? ; IF EXISTS(SELECT top 1 1 FROM sys.syscomments WHERE text LIKE ''%test% ...
- Gradle学习系列之七——依赖管理
在本系列的上篇文章中,我们讲到了如何使用java Plugin,在本篇文章中,我们将讲到Gradle的依赖管理. 请通过以下方式下载本系列文章的Github示例代码: git clone https: ...
- 数论 - 组合数学 + 素数分解 --- hdu 2284 : Solve the puzzle, Save the world!
Solve the puzzle, Save the world! Problem Description In the popular TV series Heroes, there is a ta ...
- KMP算法 - 求最小覆盖子串
KMP与最小覆盖子串 最小覆盖子串:对于某个字符串s,它的最小覆盖子串指的是长度最小的子串p,p满足通过自身的多次连接得到q,最后能够使s成为q的子串. 比如: 对于s="abcab&quo ...
- C#使用 UdpClient 类进行简单通信的例子
UdpClient 类提供了一些简单的方法,用于在阻止同步模式下发送和接收无连接 UDP 数据报. 因为 UDP 是无连接传输协议,所以不需要在发送和接收数据前建立远程主机连接.但您可以选择使用下面两 ...
- ECMall如何支持SSL连接邮件服务器的配置
首先,主要是ecmall使用的phpmailer版本太低,不支持加密连接. 然后,得对相应代码做一定调整. 1. 覆盖phpmailer 请从附件进行下载: http://files.cnblogs. ...
- B/S和C/S的区别(转)
一.什么是CS和BS结构? 1.C/S又称Client/Server或客户/服务器模式.服务器通常采用高性能的PC.工作站或小型机,并采用大型数据库系统,如Oracle.Sybase.Informix ...
- 硅谷新闻3--使用Android系统自带的API解析json数据
NewsCenterPagerBean2 bean2 = new NewsCenterPagerBean2(); try { JSONObject object = new JSONObject(js ...
- SystemClock.sleep和Thread.sleep的区别(转)
在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实 Android平台还提供了一个SystemClock.sleep方 ...