HDU 4044 GeoDefense(树形DP+分组背包)

来源:互联网 发布:c window 编程 编辑:程序博客网 时间:2024/05/29 15:54

GeoDefense

Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1239    Accepted Submission(s): 549


Problem Description
Tower defense is a kind of real-time strategy computer games. The goal of tower defense games is to try to stop enemies from reaching your bases by building towers which shoot at them as they pass.

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.
 

Input
The input consists of several test cases. The first line is an integer T (1 <= T <= 20), which shows the number of the cases.
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.
 

Output
For each test case, output a line containing the highest HP value of your enemy that you can deal with. It means that if your enemy’s HP is larger than that highest value, you can’t guarantee your victory.
 

Sample Input
221 2303 10 20 20 40 30 503 10 30 20 40 30 4542 13 11 4603 10 20 20 40 30 503 10 30 20 40 30 453 10 30 20 40 30 353 10 30 20 40 30 35
 

Sample Output
7080
 

Source
The 36th ACM/ICPC Asia Regional Beijing Site —— Online Contest
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  4043 4050 4049 4042 4045 
 


题目大意:

    有一个树形的塔防游戏地图,敌人从根结点出现,基地在每个叶子结点,在每个结点都有几个防御塔选项(每一个都有花费和攻击力),我们可以选择一个建造或不建造,当敌人经过有防御塔的结点时它会损失防御塔攻击力的hp,敌人可能向任一一个叶子结点走,给出金钱数,求一定能够杀死的敌人的最大hp。


解题思路:

    明显的树形dp,不过在树形dp状态转移的时候,我们需要给不同的子结点分配不同的金钱使得攻击力的最小值最大,这就成了一个分组背包问题。把每个子结点看作一组,每个子结点的不同花费看作一组的不同物品,进行分组背包,最后再在其基础上加上这个结点的炮塔,进行01背包,就完成了状态的转移。(详情见代码)


AC代码:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <map>using namespace std;#define INF 0x3f3f3f3f#define fi first#define se second#define P pair<int,int>const int MAXN=1000+3;//节点数const int MAXM=200+3;//总钱数const int MAXK=50+3;//选择数int N,M,K;int dp[MAXN][MAXM];//节点i,花费j的最大伤害int tmp[MAXN];vector<int> G[MAXN];vector<P> op[MAXN]; void dfs(int u,int pre){    if(G[u].size()==1&&G[u][0]==pre)//叶子结点    {        for(int i=0;i<=M;++i)            dp[u][i]=0;        for(int i=M;i>=0;--i)            for(int j=0;j<op[u].size();++j)                if(op[u][j].fi<=i)                    dp[u][i]=max(dp[u][i],op[u][j].se);        return;    }    //先用分组背包处理从子结点中取物品    for(int i=0;i<=M;++i)        dp[u][i]=INF;    for(int i=0;i<G[u].size();++i)//每个分组    {        int v=G[u][i];        if(v==pre)            continue;        dfs(v,u);        for(int j=M;j>=0;--j)//总花费        {            int t=0;            for(int k=0;k<=j;++k)//分配给子结点的花费,看作同一组的不同物品                t=max(t,min(dp[u][j-k],dp[v][k]));            dp[u][j]=t;        }    }    //再添加这个结点的防御塔建设    for(int i=0;i<=M;++i)        tmp[i]=dp[u][i];//因为存在花费为0的选择,所以必须要先保存上一行的状态    for(int i=M;i>=0;--i)    {        for(int j=0;j<op[u].size();++j)            if(op[u][j].fi<=i)                dp[u][i]=max(dp[u][i],tmp[i-op[u][j].fi]+op[u][j].se);    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&N);        for(int i=1;i<=N;++i)        {            G[i].clear();            op[i].clear();        }        for(int i=1;i<N;++i)        {            int a,b;            scanf("%d%d",&a,&b);            G[a].push_back(b);            G[b].push_back(a);        }        scanf("%d",&M);        for(int i=1;i<=N;++i)        {            int k;            scanf("%d",&k);            for(int j=0;j<k;++j)            {                int c,v;                scanf("%d%d",&c,&v);                op[i].push_back(make_pair(c,v));            }        }        dfs(1,0);        printf("%d\n",dp[1][M]);    }        return 0;}

0 0
原创粉丝点击