题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011
题目大意:
外星球上一共有N个山洞,以N-1条通道相连,就是一个树的结构,山洞里有一些虫子,每个山洞里有敌方首领的可能性,部队要去消灭他们,并要制定一套最大可能性制服首领的方案,其实就是找一条最大可能性和的路径。每个士兵能对付20只虫子,现在有m个士兵,从1号山洞出发,求最大可能性的和。
解题小结:
标准树形动态规划,用opt[i][j]表示在以i号洞口为根的子树里共派出j个人所能获得的最大值。我的程序要特判一下m=0的情况。
方程:opt[i][j]=Max(opt[i][j],opt[i][j-k]+opt[son[i]][k]),k枚举派去孩子节点的士兵数目。
代码:
#include <iostream>
using namespace std;
int n,m,Need,Num[101],opt[101][101],num[101],v[101],Visit[101];
bool f[101][101];
int Max(int x,int y)
{
if (x>y)
return x;
return y;
}
void Dfs(int t)
{
int Need,i,j,k;
Visit[t]=1;
Need=(Num[t]+19)/20;
for (i=Need;i<=m;i++)
opt[t][i]=v[t];
for (i=1;i<=n;i++)
if (f[t][i]&&!Visit[i])
{
Dfs(i);
for (j=m;j>=Need;j--)
for (k=1;k<=j-Need;k++)
opt[t][j]=Max(opt[t][j],opt[t][j-k]+opt[i][k]);
}
/*if (opt[t][0]>0)
{
opt[t][1]=Max(opt[t][1],opt[t][0]);
opt[t][0]=0;
}*/
}
void init()
{
int i,x,y;
memset(f,0,sizeof(f));
memset(Visit,0,sizeof(Visit));
memset(opt,0,sizeof(opt));
for (i=1;i<=n;i++)
cin >> Num[i] >> v[i];
for (i=1;i<=n-1;i++)
{
cin >> x >> y;
f[x][y]=1;
f[y][x]=1;
}
}
int main()
{
while (cin >> n >> m&&n!=-1)
{
init();
if(m==0) {cout << "0\n";continue;}
Dfs(1);
cout << opt[1][m] << endl;
}
return 0;
}
])