hdu 4044 GeoDefense 树形dp+分组背包

/*
题意:
     一棵树(编号1-n),1是敌人出口(只有一个敌人)。
叶子节点是我军。在节点处装大炮。每个节点有 k 种大炮选择,
可是每个节点最多装一个大炮。每个大炮有一个花费和一个威力值。
你一共有m钱,怎么能使威力值最大。敌人去攻击哪个我军是任意的,
所以最大威力是每条路值和的最小值。大炮放在叶子节点也是管用的。
思路:
     每个节点所能得到的power应该去儿子节点的最小值,
然后加上本节点建塔所得的power。因为你要保证一定能守得住。
所以得考虑最坏情况,然后尽量最优安排,使这个最坏情况尽量的好。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=1002;
const int maxm=202;
const int inf=1<<29;
int n,m,t,num,dp[maxn][maxm],hp[maxn][maxm];
vector<int>p[maxn];
void init()
{
    int i,j;
    for(i=0; i<=n; i++)
    {
        p[i].clear();
         for(j=0; j<=m; j++)
         {
          hp[i][j]=0;
          dp[i][j]=inf;
         }
    }
}
void dfs(int u,int fa)
{
    int i,j,k,v,cnt=p[u].size();
    if(u!=1&&cnt==1)///叶子节点
    {
        for(i=m; i>=0; i--)
        {
            dp[u][i]=hp[u][i];
        }
        return;
    }
    for(i=0; i<cnt; i++)
    {
        v=p[u][i];
        if(v==fa)continue;
        dfs(v,u);
        for(j=m; j>=0; j--)
        {
            int mmin=0;
            for(k=0; k<=j; k++)///找到孩子节点的最小值中的最大值
            {
                mmin=max(mmin,min(dp[u][j-k],dp[v][k]));
            }
            dp[u][j]=mmin;///没有选择根节点
        }
    }
    for(j=m; j>=0; j--)///根节点选择了一组数据
    {
        for(k=0; k<=j; k++)
        {
            dp[u][j]=max(dp[u][j],dp[u][j-k]+hp[u][k]);
        }
    }
}
int main()
{
    scanf("%d",&t);
    int i,j,u,v,cost,power;
    while(t--)
    {
        scanf("%d",&n);
        init();
        for(i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            p[u].push_back(v);
            p[v].push_back(u);
        }
        scanf("%d",&m);
        for(i=1; i<=n; i++)
        {
            scanf("%d",&num);
            for(j=1; j<=num; j++)
            {
                scanf("%d%d",&cost,&power);
                hp[i][cost]=max(hp[i][cost],power);
            }
        }
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=m; j++)
            {
                hp[i][j]=max(hp[i][j],hp[i][j-1]);
            }
        }
        dfs(1,0);
        printf("%d\n",dp[1][m]);
    }
    return 0;
}
/*
4
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

*/

你可能感兴趣的:(hdu 4044 GeoDefense 树形dp+分组背包)