题意是:进攻蚁穴,给定蚁穴里面蚁的数量及获得大脑的概率,求获得大脑的最大的概率。。。。
的确一看就知道是个树型动规,我也是刚接触树型动规。开始的时候建树的方法和1561的方法一样,但是打完后,才知道错了。
HDU 1561的搜树是从叶子节点开始的,这个题目是从根节点开始的,所以建树的方法不同。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int req,val;
}q[108];
int map[108][108],dp[108][108];
int vis[108];
int n,m;
void dfs(int x,int y){
int ant=(q[x].req+19)/20;
int i,j;
//printf(" %d",x);
for(i=m;i>=ant;i--) dp[x][i]=q[x].val;
for(i=1;i<=n;i++){
if(map[x][i]==1 && y != i){
dfs(i,x);
for(j=m;j>=ant;j--){
for(int z=1;z<=j-ant;z++){
dp[x][j]=max(dp[x][j],dp[x][j-z]+dp[i][z]);
}
}
}
}
//printf("%d %d\n",x,dp[x][m]);
}
int main(){
int i,j,a,b;
while(scanf("%d%d",&n,&m) && n != -1 && m != -1){
for(i=1;i<=n;i++) scanf("%d%d",&q[i].req,&q[i].val);
memset(map,0,sizeof(map));
memset(dp,0,sizeof(dp));
for(i=1;i<+n;i++){
scanf("%d%d",&a,&b);
map[a][b]=1;
map[b][a]=1;
}
if(m==0){
printf("0\n"); continue;
}
dfs(1,-1);
printf("%d\n",dp[1][m]);
}
return 0;
}
HDU 1561的建树方法简单一些,直接开一维保存前驱和后继:
1561的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[208][208],head[208],son[208],q[208];
int n,m;
int dfs(int x){
int i,j,ant;
int total=1;
dp[x][1]=q[x];
for(int z=son[x];z != -1;z = head[z]){
total+=dfs(z);
for(i=total;i>=1;i--){
for(j=1;j+i<=total+1;j++){
dp[x][i+j]=max(dp[x][i+j],dp[x][i]+dp[z][j]);
}
}
}
return total;
}
int main(){
int i,j,sum,a;
while(scanf("%d%d",&n,&m) && m && n ){
memset(son,-1,sizeof(son));
q[0]=0;
for(i=1;i<=n;i++){
scanf("%d%d",&a,&q[i]);
head[i]=son[a];
son[a]=i;
}
memset(dp,0,sizeof(dp));
dfs(0);
printf("%d\n",dp[0][m+1]);
}
return 0;
}
路途中。。。。。