博览会(树形DP)

48 篇文章 1 订阅
15 篇文章 0 订阅

题目描述
某市正在举行一场大型博览会,博览会有 n 个展馆,每个展馆里有若干个展台。这 n 个展馆以 及它们之间的道路可以看成一棵二叉树,博览会的出入口设在根节点——1 号展馆,小明将从这里 出发乘坐电瓶车到各个展馆参观,并最终回到 1 号展馆出口。
由于路程差异,乘坐电瓶车往返不同展馆间的费用也有所区别。出发时,小明的乘车卡里余额 为 k。他现在想知道,若全程都乘坐电瓶车,他最多能参观多少个展台?
说明:只要小明到达了某个展馆,就会参观该展馆内的所有展台,若多次参观同一个展台不重复计算。

输入
输入共 n+2 行:
第 1 行为 2 个整数 n、k,用一个空格隔开,表示展馆个数和小明乘车卡初始余额。
第 2 行为 n 个数,用一个空格隔开,表示 1 号至 n 号各展馆的展台数目。
接下来 n 行,每行 4 个数,用一个空格隔开;第 i+2 行 4 个数分别表示展馆 i 左子节点展馆号、 到左子节点展馆的费用、右子节点展馆号、到右子节点展馆的费用。如果子节点展馆号为 0 则表示 没有对应的子节点展馆。

输出
输出共 1 行,1 个整数,表示小明最多能参观的展台数量。

样例输入
10 20
2 8 5 1 10 5 9 9 3 5
2 1 3 2
4 8 5 2
6 2 7 2
8 3 9 6
0 0 10 2
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

样例输出
39

提示
根据样例数据,可以得到如下展馆二叉树示意图(每个圈内标示了展馆号及展台数):
在这里插入图片描述
由图可知,小明沿红色箭号路径,到 1、2、5、3、6、7 这六个展馆参观并返回,往返乘车费用 为 18,参观展台数为 39,为能够实现的最大值。

对于 40%的数据:n≤10;k≤20;
对于 100%的数据:n≤50;k≤100;
所有展馆的展台总数不超过 105

思路
树形DP找最大值

代码实现

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=105;
const int M=35;
const int INF=0x3f3f3f;
const ull sed=31;
const ll mod=998244353;
const double eps=1e-8;
typedef pair<int,int>P;
typedef pair<double,double>Pd;

struct node
{
    int v,l,lc,r,rc;
}E[N];
int n,k,dp[N][N];

int dfs(int x,int tot)
{
    if(dp[x][tot]) return dp[x][tot];
    if(E[x].l&&E[x].r)for(int i=E[x].lc;i<=tot-E[x].rc;i++) dp[x][tot]=max(dp[x][tot],dfs(E[x].l,i-E[x].lc)+dfs(E[x].r,tot-i-E[x].rc));
    if(E[x].l && E[x].lc<=tot) dp[x][tot]=max(dp[x][tot],dfs(E[x].l,tot-E[x].lc));
    if(E[x].r && E[x].rc<=tot) dp[x][tot]=max(dp[x][tot],dfs(E[x].r,tot-E[x].rc));
    dp[x][tot]+=E[x].v;
    return dp[x][tot];
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&E[i].v);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&E[i].l,&E[i].lc,&E[i].r,&E[i].rc);
        E[i].lc*=2;E[i].rc*=2;
    }
    printf("%d\n",dfs(1,k));
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值