P5194 [USACO05DEC]Scales S

题意:给你一个不降序序列(序列长度N),然后让你求能够组成的最大的不超过c的值是多少

一开始想的是价值和重量相等的01背包问题,但是发现c的范围是有符号整数([-2^{31},2^{31}-1])

改用暴力,基本方法是二进制枚举,但是需要一些剪枝:

  1. 如果中间发现sum > c 就return
  2. 如果发现sum + s[u] (s为w的前缀和)满足 <= c 就更新ans = max(ans, sum + s[u]) 并return
  3. 如果发现sum + s[u] 满足 <= ans 直接return 没必要再做了

另外的话,题目中的每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。假设砝码序列为a,并且a[0], a[1] 取非零数字中最小的1,并且a[i] = a[i 1] + a[i - 2]那么a为斐波那契序列,由于斐波那契序列在第47项时>(2^{31}-1),所以题目中的(N < 47)

#include<iostream>
using namespace std;

const int N = 1010;

#define int long long

int w[N], s[N];
int n, c;
int ans;

void dfs(int u, int sum){
    if(sum > c) return;
    if(sum + s[u] <= ans) return;
    if(sum + s[u] <= c){
        ans = max(ans, sum + s[u]);
        return;
    }
    if(u == -1){
        ans = max(sum, ans);
        return;
    }
    dfs(u - 1, sum);
    dfs(u - 1, sum + w[u]);
}

signed main(){
    cin >> n >> c;
    for(int i = 1; i <= n; i ++) cin >> w[i];
    for(int i = 1; i <= n; i ++) s[i] = w[i] + s[i - 1];
    dfs(n, 0);
    cout << ans << endl;
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/15343482.html