Codevs_P2144 砝码称重 2

时间限制: 1 s
空间限制: 16000 KB
题目等级 : 钻石 Diamond

题目描述 Description
有n个砝码,现在要称一个质量为m的物体,请问最少需要挑出几个砝码来称?

注意一个砝码最多只能挑一次

输入描述 Input Description
第一行两个整数n和m,接下来n行每行一个整数表示每个砝码的重量。

输出描述 Output Description
输出选择的砝码的总数k,你的程序必须使得k尽量的小。

样例输入 Sample Input
3 10
5
9
1

样例输出 Sample Output
2

数据范围及提示 Data Size & Hint
1<=n<=30,1<=m<=2^31,1<=每个砝码的质量<=2^30

思路分析:对前面n/2个数生成所有可能的组合得到数集合A,以及得到这些数的最少需要的砝码个数,map或者hashmap存起来,我用的stl的map就行

然后对后面n/2数同样处理,得到集合B以及生成B中每个数至少需要的砝码。

然后对前面得到的所有的数a∈A,遍历是否M-a是否在B中,然后取前后两部分生成a b最少需要砝码个数的和中最小的

对于如何得到前面后面n/2个数生成所有可能的组合得到数集合,可以先得到一个数组合得到的所有数,然后在此基础上得到两个数组合得到的所有数,再再次基础上得到三个数能够组和的所有数。为了防止一个数被用两次,可以记录得到这些数的最大下标

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int main()
{
    int n,m,a[33],i,j,ans=1000000007;
    map<int,int>mm;
    cin>>n>>m;
    for(i=0;i<n;i++)
        cin>>a[i];
    for(i=1;i<(1<<(int)(n/2+1));i++)
    {
        int sum=0,cnt=0;
        for(j=0;j<n/2;j++)
            if(i&(1<<j)) sum+=a[j],cnt++;
        if(!mm[sum]||cnt<mm[sum]) mm[sum]=cnt;
    }
    if(mm[m]) ans=mm[m];
    for(i=1;i<(1<<(int)((n+1)/2+1));i++)
    {
        int sum=0,cnt=0;
        for(j=0;j<(n+1)/2;j++)
            if(i&(1<<j)) sum+=a[j+n/2],cnt++;
        if(sum==m) ans=min(ans,cnt);
        if(mm[m-sum]) ans=min(ans,mm[m-sum]+cnt);
    }
    cout<<ans<<endl;
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值