树形背包。代码如下:
#include<iostream>
#include<vector>
using namespace std;
int n,m;
int num[105],brain[105];
int dp[105][105];
int vis[105];
vector<int> map[105];
int max(int a,int b)
{
return a>b?a:b;
}
void dfs(int u)
{
int i,j,k;
vis[u]=1;
int tt=(num[u]+19)/20;
for(i=tt;i<=m;i++)
dp[u][i]=brain[u];
for(i=0;i<map[u].size();i++)
{
int temp=map[u][i];
if(vis[temp]) continue;
dfs(temp);
for(j=m;j>=tt;j--)
for(k=1;k<=m;k++)
{
if(j-k>=tt)
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[temp][k]);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&(m!=-1||n!=-1))
{
int i,u,v;
for(i=1;i<=n;i++)
scanf("%d%d",&num[i],&brain[i]);
for(i=1;i<=n;i++)
map[i].clear();
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
map[u].push_back(v);
map[v].push_back(u);
}
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
if(m==0)
{
printf("0\n");
continue;
}
dfs(1);
printf("%d\n",dp[1][m]);
}
return 0;
}
或者:
#include<iostream>
#include<vector>
using namespace std;
int n,m;
int num[105],brain[105];
int dp[105][105],f[105][105];
int vis[105];
vector<int> map[105];
int max(int a,int b)
{
return a>b?a:b;
}
void dfs(int u)
{
int i,j,k;
vis[u]=1;
for(i=0;i<map[u].size();i++)
{
int temp=map[u][i];
if(vis[temp]) continue;
dfs(temp);
for(j=m;j>=0;j--)
for(k=1;k<=m;k++)
/**//*此处须从1开始,因为不存在没人还往后继节点走的情况!(由于可能
出现dp[temp][0]!=0的情况,如果此处k==0,则代表该分组不被选择的情
况,在这种情况下却加上了一个不为0的dp[temp][0],显然矛盾。因此
从1开始。如果要从0开始,dp[temp][0]应该等于0.)*/
{
if(j>=k)
f[u][j]=max(f[u][j],f[u][j-k]+dp[temp][k]);
}
}
int tt=(num[u]+19)/20;
for(i=tt;i<=m;i++)
dp[u][i]=f[u][i-tt]+brain[u];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&(m!=-1||n!=-1))
{
int i,u,v;
for(i=1;i<=n;i++)
scanf("%d%d",&num[i],&brain[i]);
for(i=1;i<=n;i++)
map[i].clear();
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
map[u].push_back(v);
map[v].push_back(u);
}
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
if(m==0)
{
printf("0\n");
continue;
}
dfs(1);
printf("%d\n",dp[1][m]);
}
return 0;
}
posted on 2010-08-07 01:25
wuxu 阅读(1335)
评论(0) 编辑 收藏 引用 所属分类:
动态规划