//运行时间 2683 MS
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
struct Vertex{
int v;
Vertex* next;
}vertex[215];
Vertex* head[102];
int men,n,men_needed[102],brains[102],a,b,dp[102][102],cnt;
bool visited[102];
void link(int a,int b){
vertex[++cnt].v = b;
if(head[a]==NULL) {
head[a] = &vertex[cnt];
vertex[cnt].next = NULL;
}
else {
vertex[cnt].next = head[a];
head[a] = &vertex[cnt];
}
}
int R[102][102];
int solve(int i,int men_left){
if(R[i][men_left]) return R[i][men_left];
if(men_left<men_needed[i]||men_left==0) return 0; //注意 <span style="font-family: Arial, Helvetica, sans-serif;">men_left==0 的情况时返回0 ,</span><span style="font-family: Arial, Helvetica, sans-serif;"> 虽然有时候不需要士兵去战斗,但需要士兵去拿brains </span>
visited[i] = true;
int men_left0 = men_left;
men_left-=men_needed[i];
Vertex* p = head[i];
int Max=-1;
int dp[2][men_left+1],k=1;
memset(dp,0,sizeof(dp));
while(p!=NULL) {
if(men_left<men_needed[p->v]||visited[p->v]) { p = p->next; continue; }
for(int men=0;men<=men_left;men++) { //给当前 分支 总共分配 men 个士兵
dp[k][men] = 0;
for(int j=0;j<=men;j++){ //给当前 p->v 分配 j 个
dp[k][men] = max( dp[k][men] , dp[!k][men-j] + solve(p->v,j) );
}
}
p = p->next;
k = !k;
}
visited[i] = false;
R[i][men_left0] = brains[i] + dp[!k][men_left];
return brains[i] + dp[!k][men_left];
}
int main(){
while(scanf("%d%d",&n,&men)!=EOF&&(n!=-1||men!=-1)){
memset(visited,0,sizeof(visited));
memset(R,0,sizeof(R));
cnt = -1;
for(int i=0;i<102;i++) head[i] = NULL;
for(int i=1;i<=n;i++){
scanf("%d%d",&men_needed[i],&brains[i]);
if(men_needed[i]>0) men_needed[i]=(men_needed[i]-1)/20+1;
}
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
link(a,b);
link(b,a);
}
printf("%d\n",solve(1,men));
}
}
上面的代码效率不够高。
//运行时间 93 MS
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip>
using namespace std;
const int inf = 0x7FFFFFFF;
const int maxn = 111;
struct node{
int v;
node *next;
}tree[maxn<<1], *head[maxn];
int ptr,n,sum;
int dp[105][2005], bug[105], w[105];
bool vis[105];
void AddEdge(int a,int b){
tree[ptr].v=a;
tree[ptr].next=head[b];
head[b]=&tree[ptr++];
}
int DFS(int cnt,int M){
if(M==0) return 0;
int m=M-bug[cnt];
vis[cnt]=true;
node *p=head[cnt];
int Max=0;
while(p!=NULL){
if(vis[p->v]){
p = p->next; continue;
}
for(int i=m ; i>=bug[p->v] ; --i){
dp[p->v][i]=DFS(p->v,i);
//cout<<p->v<<' '<<i<<"=="<<dp[p->v][i]<<endl;
}
for(int i=m;i>=bug[p->v];--i) // i 为士兵个数
for(int j=i;j>=bug[p->v];--j)
dp[cnt][i]=max( dp[cnt][i] , dp[cnt][i-j]+dp[p->v][j] );
p=p->next;
} //cout<<cnt<<' '<<m<<"=="<<dp[cnt][m]<<endl;
return w[cnt]+dp[cnt][m];
}
int main(){
int a=inf+1;
int m;
while(~scanf("%d%d",&n,&m)&&!(n==-1&&m==-1)){
ptr=1;
for(int i=1;i<=n;++i){
int a; scanf("%d%d",&a, w+i);
bug[i]=(a%20)?1:0;
bug[i]+=a/20;
//if(bug[i]==0) bug[i]=1;
}
memset(head,0,sizeof(head));
for(int i=1;i<n;++i){
int a,b; scanf("%d%d",&a,&b);
AddEdge(b,a); AddEdge(a,b);
}
if(m<bug[1]){
puts("0"); continue;
}
memset(dp,0,sizeof(dp));
memset(vis,false,sizeof(vis));
int ans=DFS(1,m);
printf("%d\n",ans);
}
return 0;
}