这算是 经典的树形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
",0);continue;}
printf("%d
",dp[1][m]);
}
}