HDU 1011 Starship Troopers

这算是 经典的树形DP 入门题吧:

  题目的意思: 一个由N个点形成的树状网络;进入点是1;现在每个节点

  有俩个属性 1:防守的人数,2 打败防守人数的奖励;

  问由N个人组队去赚钱 最多赚多少:注一个人可以打败20个防守渣渣(这就是传说中的战五渣)!对于需要的人数取ceil();

很经典的  依赖性的背包; dp[i][j] (  节点i 为跟 有J个士兵 可以得到多少奖励 )  这道题 有坑点不要写错!假如一个节点的的防守人数是0, 你不必 在这个节点留人,但是必须有人经过这点;

  

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
using namespace std;
const int maxn=101;
struct Edge
{
    int to,pre;
    Edge(){}
    Edge(int to,int pre):to(to),pre(pre){}
};
struct info
{
    int bug,money;
    info(){}
    void input()
    {
        scanf("%d%d",&bug,&money);
        bug=(bug+19)/20;
    }
};
info ko[maxn];
Edge edge[maxn*2+1];
int head[maxn],pos;
int dp[maxn][maxn];
void inint()
{
    pos=0;
    memset(dp,0,sizeof(dp));
    memset(head,-1,sizeof head);
}
void add_edge(int s,int to)
{
    edge[pos]=Edge(to,head[s]);
    head[s]=pos++;
}
int n,m;
void dfs(int &fa,int &s)
{
    for(int i=ko[s].bug;i<=m;i++)
        dp[s][i]=ko[s].money;
    for(int i=head[s];~i;i=edge[i].pre)
    {
        Edge & tmp=edge[i];
        if(tmp.to==fa)continue;
        dfs(s,tmp.to);
//根节点是必须取,所以W>ko[s].bug; for(int w=m;w>ko[s].bug;w--)for(int j=ko[s].bug;j<w;j++) dp[s][w]=max(dp[s][w],dp[s][j]+dp[tmp.to][w-j]); } } int main() { int a,b; while(~scanf("%d%d",&n,&m)) { inint(); if(n==-1&&m==-1) return 0; for(int i=1;i<=n;i++)ko[i].input(); for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } a=-1,b=1; dfs(a,b); if(m==0){printf("%d\n",0);continue;} printf("%d\n",dp[1][m]); } }

  

posted @ 2014-09-04 14:00  默默无语敲代码  阅读(183)  评论(0编辑  收藏  举报