hdu 4044 GeoDefense 树形dp+分组背包

来源:互联网 发布:mac默认网关 编辑:程序博客网 时间:2024/05/19 10:56
/*题意:     一棵树(编号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;}/*421 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*/