[bzoj1673]天平

题目描述

约翰有一架用来称牛的体重的天平.与之配套的是N(1≤N≤1000)个已知质量的砝码(所有砝码质量的数值都在31位二进制内).每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(约翰不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当约翰把砝码放到她的蹄子底下,她就会尝试把砝码踢到约翰脸上).天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于C(1≤C<2^30)时,天平就会被损坏. 砝码按照它们质量的大小被排成一行.并且,这一行中从第3个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和. 约翰想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少.由于天平的最大承重能力为C.他不能把所有砝码都放到天平上.
现在约翰告诉你每个砝码的质量,以及天平能承受的最大质量.你的任务是选出一些砝码,
使它们的质量和在不压坏天平的前提下是所有组合中最大的.

搜索

因为权值在int内,那么按照斐波那契40多项就会爆。
因此n<=40。
我们考虑搜索咯。
枚举每个选不选,这样跑不过。
可以考虑加可行性减枝(或者叫最优性减枝?),如果剩余数全选还是不比当前答案大那就退了吧。
为了让这个减枝发挥效果,当然要倒着搜啦。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
int a[1500];
ll sum[1500];
int i,j,k,l,t,n,m,ans;
void dfs(int x,int y){
    if (y>m) return;
    ans=max(ans,y);
    if (!x) return;
    if (y+sum[x]<=ans) return;
    dfs(x-1,y+a[x]);
    dfs(x-1,y);
}
int main(){
    scanf("%d%d",&n,&m);
    fo(i,1,n) scanf("%d",&a[i]);
    fo(i,1,n) sum[i]=sum[i-1]+a[i];
    /*fd(i,n,1)
        if (ans<=m-a[i]) ans+=a[i];*/
    dfs(n,0);
    printf("%d\n",ans);
}
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页