HDU 1011

题意是:进攻蚁穴,给定蚁穴里面蚁的数量及获得大脑的概率,求获得大脑的最大的概率。。。。


的确一看就知道是个树型动规,我也是刚接触树型动规。开始的时候建树的方法和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;
}

路途中。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值