HDU 4044 GeoDefense 树形DP+分组背包

来源:互联网 发布:linux修改vim配置 编辑:程序博客网 时间:2024/06/10 10:44

题意:

塔防游戏。

有一棵树,现在敌人在节点1上,其他所有的叶子节点均是你的基地。

现在从节点1放出一个敌人,让你在节点上有策略性放置攻击塔(每个节点都有多种塔型选择,每个节点只能放一个塔),使得敌人所受的伤害尽量高。

你不能预测敌人走哪条路。你要保住你的基地,因此你要保证你的任何一个基地不能被攻陷。(言下之意是使得敌人所受的伤害最小值尽量大)

思路:

参考了一下bin神的思路。

定义状态:

dp[i][j]:对于以i为根节点的树,花费j元能对敌人所能造成的最大伤害。

叶子节点:

金钱允许范围内,选择伤害最大的塔。

其他节点:

每当一个儿子dfs回来后,把儿子先背上当前节点的状态。

转移:tmp = max(tmp, min(dp[u][j-p], dp[son][p])); tmp->dp[u][j];

在把所有的儿子都背上当前的节点状态后,开始把当前节点所能放置的塔背上当前的状态。

转移:tmp = max(tmp, dp[u][j-money[t]] + power[t]); tmp->dp[u][j];

code:

#include <cstring>#include <cstdlib>#include <cstdio>#include <iostream>#include <algorithm>#include <vector>#include <map>using namespace std;typedef long long LL;const int MAXN = 1005;const int MAXM = 205;const int MAXK = 55;const int INF = 0x3f3f3f3f;int dp[MAXN][MAXM];int n, m;vector <int> G[MAXN];vector <pair <int, int> >tow[MAXN];void init(){    for(int i = 1;i <= n; i++)        G[i].clear();    for(int i = 1;i <= n; i++)        tow[i].clear();}void input(){    cin>>n;    int u, v;    for(int i = 0;i < n-1; i++)    {        cin>>u>>v;        G[u].push_back(v);        G[v].push_back(u);    }    cin>>m;    int k;    int money, power;    for(int i = 1;i <= n; i++)    {        cin>>k;        while(k--)        {            cin>>money>>power;            tow[i].push_back(make_pair(money, power));        }    }}void dfs(int u, int par){    if(G[u].size() == 1 && G[u][0] == par) //the dead end;    {        memset(dp[u], 0, sizeof(dp[u]));        for(int j = m; j >= 0; j--)        {            int tmp = dp[u][j];            for(int t = 0;t < tow[u].size(); t++)                if(j >= tow[u][t].first)                    tmp = max(tmp, tow[u][t].second);            dp[u][j] = tmp;        }        return;    }    memset(dp[u], INF, sizeof(dp[u]));    for(int i = 0;i < G[u].size(); i++)    {        int v = G[u][i];        if(v == par) continue;        dfs(v, u);        //pick up the son:v        for(int j = m; j >= 0; j--)        {            int tmp = -1;            for(int p = 0;p <= j; p++)                tmp = max(tmp, min(dp[u][j-p], dp[v][p]));            dp[u][j] = tmp;        }    }    //pick up the node u 's tower    for(int j = m; j >= 0; j--)    {        int tmp = dp[u][j];        for(int t = 0;t < tow[u].size(); t++)            if(j >= tow[u][t].first)                tmp = max(tmp, dp[u][j-tow[u][t].first] + tow[u][t].second);        dp[u][j] = tmp;    }}inline void solve(){    dfs(1, -1);    cout<<dp[1][m]<<endl;}        int main(){    ios::sync_with_stdio(false);    int T;    cin>>T;    while(T--)    {        init();        input();        solve();    }    return 0;}        






0 0
原创粉丝点击