ZOJ 2111 Starship Troopers(树形DP)

来源:互联网 发布:软件配置文件用途 编辑:程序博客网 时间:2024/06/05 17:08

dp[i][j]表示在i结点上放置j个士兵能获得的最多brains数量,注意士兵并不是只能待在一个房间里,他可以把当前房间清理完,但只能往下面走.

dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[v][k])当前位置i上放j个士兵和当前位置上放j-k个士兵,下一个房间放k个士兵的最大值

#include <iostream>#include <cstdio>#include <memory.h>#include <cmath>using namespace std;const int maxn=105;#define mmax(a,b) ((a)>(b)?(a)?(b))struct edge{int v,next;}es[maxn*2];int w[maxn],v[maxn],head[maxn],dp[maxn][maxn],n,m;bool vis[maxn];void dfs(int u,int m){vis[u]=1;for (int i=w[u];i<=m;++i){dp[u][i]=v[u];}for (int ne=head[u];ne!=-1;ne=es[ne].next){int v=es[ne].v;if(!vis[v]){dfs(v,m);for (int j=m;j>=w[u];--j){for (int k=1;j-k>=w[u];++k){dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);}}}}}void addEdge(int u,int v,int eidx){es[eidx].v=v;es[eidx].next=head[u];head[u]=eidx;}int main(){while (scanf("%d%d",&n,&m)==2){if (n==-1&&m==-1)break;memset(head,-1,sizeof(head));memset(dp,0,sizeof(dp));memset(vis,0,sizeof(vis));for (int i=1;i<=n;++i){scanf("%d%d",&w[i],&v[i]);w[i]=(int)ceil(w[i]/20.0);}int eidx=0;for (int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v);addEdge(u,v,eidx++),addEdge(v,u,eidx++);}if(m==0){printf("0\n");continue;}dfs(1,m);printf("%d\n",dp[1][m]);}return 0;}