GeoDefense HDU - 4044 (树行dp+背包)

题意:

这是一个塔防游戏,地图是一个n个编号为1~n的节点的树, 节点1是敌人的基地,其他叶子节点都是你的基地。敌人的基地会源源不断地出来怪兽,为了防止敌人攻进你的基地,你可以选择造塔。每个节点最多只能造一个塔,且节点i可以有ki种塔供你选择,价钱和攻击力分别为price_i, power_i,攻击力power_i,效果是让敌人经过这个节点时让敌人的血减少power_i点。那么从敌人的基地到你的任意一个叶子基地的路径,这条路径上的所有塔的攻击力之和,就是这个基地的抵抗力。敌人的攻击路径是不确定的,为了保护你的所有基地,你要确定所有基地中抵抗力最低的一个。 你只有数量为m的钱,问最佳方案,可以抵挡敌人的最大血量是多少?也就是,让所有叶子基地中抵抗力最低的一个的值尽量大,最大是多少?

思路:

最大值最小化问题

dp[i][j]表示以节点i为根节点的子树有j元钱时的最大抵抗力,因为我们需要考虑将j元钱分配给i的子节点,所以在dfs的同时进行一次分组背包处理,结束以后在对节点进行01背包,最后dp[1][m]就是答案了。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f
int n,m;
int cnt;
int tot[maxn];
int head[maxn];
int dp[10005][300];
int num[maxn],cost[maxn][55],val[maxn][55];
struct Edge
{
    int u,v,next,w;
}edge[maxn*2];
void addedge(int u,int v,int w)
{
    cnt++;
    edge[cnt].v=v;
    edge[cnt].w=w; 
    edge[cnt].next=head[u];
    head[u]=cnt;
}
// void dfs1(int u,int pre)
// {
//     dp[u][0]=inf;
//     int t=0;
//     for(int i=head[u];i!=-1;i=edge[i].next)
//     {
//         int v=edge[i].v;
//         if(v==pre) continue;
//         dfs1(v,u);
//         for(int j=m;j>=0;j--)
//         {
//             t=0;
//             for(int k=0;k<=j;k++)
//             {
//                 t=max(t,min(dp[u][j-k],dp[v][k]));
//             }
//             dp[u][j]=t;
//         }
//     }

//     if(dp[u][0]==inf) dp[u][0]=0;
//     for(int j=m;j>=0;j--)
//     {
//         t=dp[u][j];
//         for(int i=1;i<=price[u][0];i++)
//         {
//             if(j>=price[u][i])
//             {
//                 t=max(t,dp[u][j-price[u][i]]+power[u][i]);
//             }
//         }
//         dp[u][j]=t;
//     }
// }
void dfs(int u,int fa)
{
    dp[u][0]=INF;
    int i,j,k,v,t;
    for(i=head[u];i;i=edge[i].next)
    {
        v=edge[i].v;
        if(v==fa) continue ;
        dfs(v,u);
        for(j=m;j>=0;j--)
        {
            t=0;
            for(k=0;k<=j;k++)
            {
                t=max(t,min(dp[v][k],dp[u][j-k]));
            }
            dp[u][j]=t;
        }
    }
    if(dp[u][0]==INF) dp[u][0]=0;  // 一定要加这个判断
    for(j=m;j>=0;j--)
    {
        t=dp[u][j];
        for(i=1;i<=num[u];i++)
        {
            if(j>=cost[u][i])
            {
                t=max(t,dp[u][j-cost[u][i]]+val[u][i]);
            }
        }
        dp[u][j]=t;
    }
}

int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
     int i,j,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int u,v;
        cnt=0;
        memset(head,0,sizeof(head));
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v,0);
            addedge(v,u,0);
        }
        scanf("%d",&m);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
            for(j=1;j<=num[i];j++)
            {
                scanf("%d%d",&cost[i][j],&val[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        dfs(1,0);
        printf("%d\n",dp[1][m]);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/81363206