P5194 [USACO05DEC] Scales S(DFS)

 

题目描述

约翰有一架用来称牛的体重的天平。与之配套的是 N (1≤N≤1000) 个已知质量的砝码(所有砝码质量的数值都在 32 位带符号整数范围内)。

每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(约翰不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当约翰把砝码放到她的蹄子底下,她就会尝试把砝码踢到约翰脸上)。

天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于 C (1≤C≤2^30) 时,天平就会被损坏。砝码按照它们质量的大小被排成一行。并且,这一行中从第 3 个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。

约翰想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少。由于天平的最大承重能力为 C,他不能把所有砝码都放到天平上。

现在约翰告诉你每个砝码的质量,以及天平能承受的最大质量,你的任务是选出一些砝码,使它们的质量和在不压坏天平的前提下是所有组合中最大的。

输入格式

第 1 行输入两个用空格隔开的正整数 N 和 C。

第 2 到 N+1 行:每一行仅包含一个正整数,即某个砝码的质量。保证这些砝码的质量是一个不下降序列。

输出格式

输出一个正整数,表示用所给的砝码能称出的不压坏天平的最大质量。

输入输出样例

输入 #1复制

3 15
1
10
20

输出 #1复制

11
#include <iostream>
using namespace std;
typedef long long ll;

ll n, c;
ll ans = 0;
ll a[1001], b[1001];

void dfs(int i, ll s) {
    if (s > c) return;           // 剪枝1: 砝码超重,直接返回
    ans = max(ans, s);           // 更新最大质量
    if (i < 0) return;           // 遍历结束
    if (s + b[i] <= ans) return; // 剪枝2: 剩余质量不足

    dfs(i - 1, s + a[i]);     // 选择当前砝码
    dfs(i - 1, s);    // 不选择当前砝码
}

int main() {
    cin >> n >> c;

    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    b[0] = a[0];
    for (int i = 1; i < n; i++) { // 计算前缀和 b[i],用于剪枝
        b[i] = b[i - 1] + a[i];
    }

    dfs(n - 1, 0);  // 从最后一个砝码开始搜索
    cout << ans;

    return 0;
}

剪枝:

if (s + b[i] <= ans) return;

b[i]:从第 i 个砝码开始到最后的 所有砝码质量之和(前缀和)

如果当前质量 s 加上 所有剩余砝码的质量 b[i] 仍然小于等于 ans,说明无论如何选择接下来的砝码,都不可能超过 ans,那么继续递归就没有意义了,直接返回,避免无效计算。避免 TLE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值