poj3172 Scales (dfs+前缀和剪枝)

Scales

Farmer John has a balance for weighing the cows. He also has a set of N (1 <= N <= 1000) weights with known masses (all of which fit in 31 bits) for use on one side of the balance. He places a cow on one side of the balance and then adds weights to the other side until they balance. (FJ cannot put weights on the same side of the balance as the cow, because cows tend to kick weights in his face whenever they can.) The balance has a maximum mass rating and will break if FJ uses more than a certain total mass C (1 <= C < 2^30) on one side.

The weights have the curious property that when lined up from smallest to biggest, each weight (from the third one on) has at least as much mass as the previous two combined.

FJ wants to determine the maximum mass that he can use his weights to measure exactly. Since the total mass must be no larger than C, he might not be able to put all the weights onto the scale.

Write a program that, given a list of weights and the maximum mass the balance can take, will determine the maximum legal mass that he can weigh exactly.

Input

Line 1: Two space-separated positive integers, N and C.

Lines 2…N+1: Each line contains a single positive integer that is the mass of one weight. The masses are guaranteed to be in non-decreasing order.
Output
Line 1: A single integer that is the largest mass that can be accurately and safely measured.

Sample Input

3 15
1
10
20

Sample Output

11

Hint

Explanation of the sample:

FJ has 3 weights, with masses of 1, 10, and 20 units. He can put at most 15 units on one side of his balance.

The 1 and 10 weights are used to measure 11. Any greater weight that can be formed from the weights will break the balance.

题意:

给n和c
表示有n个砝码(重量为a[1]—a[n],物品重量递增),最大容量为c
问最多选多重的砝码,砝码总重量不超过c

分析:

第一眼看起来是01背包,但是背包大小c最大在230,所以不太行
物品数量在1000 ,考虑dfs搜索
但是直接dfs会超时,需要剪枝
这里利用前缀和剪枝
从后往前搜:
如果把前面砝码的全部都选了答案都不会比ans大,就直接退出搜索

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<algorithm>
#include<sstream>
#define ll long long
//void fp(){freopen("1.txt","r",stdin);freopen("2.txt","w",stdout);}
const int inf=0x3f3f3f3f;
const int inn=-(1<<30);
using namespace std;
const int maxm=1e3+5;
ll a[maxm];
ll sum[maxm];
ll ans,n,c;
void dfs(int cur,ll num){
    if(num>ans)ans=num;
    if(cur<1)return ;
    for(int i=cur;i>=1;i--){
        if(sum[i]+num<=ans)return ;//剪枝
        if(num+a[i]>c)continue;
        dfs(i-1,num+a[i]);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin>>n>>c;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=a[i]+sum[i-1];
    }
    dfs(n,0);
    cout<<ans<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值