HDU-4044 GeoDefense tree dp + 01 [backpack]

The meaning of problems

A tower defense game, the map is a tree of n nodes consisting of (1-n), where a node is the enemy spawn point, all leaf nodes is our base . On each node has a different towers can be built, but each node can only build one .
Towers price and hurt two properties. When a node through enemy will attack damage value of the towers of the node.
Given assets m m , in seekingto ensure that the enemy can not cross the leaf nodethe maximum value of the enemy's life under the conditions, can resist, even if the smallest sum attack from a node to all leaf nodes of the path the maximum.

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




answer

  • The definition states: d p [ i ] [ j ] dp[i][j] represents i i node, spend j j withinthe largest and最小攻击力.
  • Pretreatment each node: m a x _ d m g [ i ] [ j ] max\_dmg[i][j] indicates that the flower on the i-node j j greatest harm to the cost-effectiveness of building a tower can get
  • State transition: For each non-leaf node, its state is the source of all its child nodes. Let's draw is not it the case of the tower above the state, and then come to the tower state.
  • Do not build the tower: d p [ x ] [ p ] = max ( min ( d p [ v ] [ k ] )     k = p v s o n s ( x ) , v 1 v 2 ) dp[x][p] =\max( \min(dp[v][k])\ |\ \sum k=p,v∈sons(x), v1 \ne v2)
  • The tower: knapsack problem







#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pr pair<int, int>
const int maxn=4000, maxp=250;

int n, m, T, ans;

int a[maxn];
int dp[maxn][maxp];
int max_dmg[maxn][maxp];

struct node{
    int v, next;
}e[maxn*2];
int head[maxn], cnt;

void add(int u, int v)
{
    e[cnt].v = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

void dfs(int x, int fa)
{
    int num = 0;
    for(int i=head[x];i!=-1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fa) continue;
        num++;
        dfs(v, x);
        for(int j=m;j>=0;j--)
        {
            int t = 0;
            for(int k=0;k<=j;k++)
            {
                // 先考虑x节点不建塔的情况
                t = max(t, min(dp[v][k], dp[x][j-k]));
                // dp[x][j] = max( min( dp[v][k] | sum(k) = j ) )
                // 划分j的费用给x点和它的子节点v
            }
            dp[x][j] = t;
        }
    }
    
    // 下面是在x上建塔的情况(在不建塔的情况的基础上)
    if(!num){
        dp[x][0] = 0;
        for(int i=0;i<=m;i++)
            dp[x][i] = max_dmg[x][i];
        return;
    }
    
    for(int i=m;i>=0;i--)
    {
        for(int j=0;j<=i;j++)
        {
            dp[x][i] = max(dp[x][i-j]+max_dmg[x][j], dp[x][i]);
        }
    }
}

int main()
{
    cin >> T;
    int x, y;
    while(T--)
    {
        cnt = 0;
        memset(head, -1, sizeof head);
        memset(max_dmg, 0, sizeof max_dmg);
        cin >> n;
        for(int i=0;i<n-1;i++)
        {
            cin >> x >> y;
            add(x, y);
            add(y, x);
        }
        cin >> m;
        for(int i=1;i<=n;i++)
        {
            int K;
            cin >> K;
            for(int j=0;j<K;j++)
            {
                cin >> x >> y;
                max_dmg[i][x] = max(max_dmg[i][x], y);
            }
            for(int j=1;j<=m;j++)
                max_dmg[i][j] = max(max_dmg[i][j-1], max_dmg[i][j]);
        }
        
        memset(dp, 0x3f, sizeof dp);
        dfs(1, 0);
        cout << dp[1][m] << endl;
    }
    return 0;
}

Published 40 original articles · won praise 15 · views 1809

Guess you like

Origin blog.csdn.net/irimsky/article/details/104825928