持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
砝码称重
题目描述
现有 个砝码,重量分别为 ,在去掉 个砝码后,问最多能称量出多少不同的重量(不包括 )。
请注意,砝码只能放在其中一边。
输入格式
第 行为有两个整数 和 ,用空格分隔。
第 行有 个正整数 ,表示每个砝码的重量。
输出格式
仅包括 个整数,为最多能称量出的重量数量。
样例 #1
样例输入 #1
3 1
1 2 2
样例输出 #1
3
提示
【样例说明】
在去掉一个重量为 的砝码后,能称量出 共 种重量。
【数据规模】
对于 的数据,。
对于 的数据,。
对于 的数据,。
对于 的数据,, ,,。
解题思路:二进制枚举
首先用一个的循环枚举状态,然后用popcount判断是否满足条件。
int table[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
int popcount(unsigned int x) { // 返回x的二进制中1的个数
int ret = 0;
for(int i = 0; i < 8; i++) ret += table[x & 15], x >>= 4;
return ret;
}
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int w[30];
int ans = -inf;
int count_one(int x)//x的二进制中第0到n-1位中1的个数
{
int cnt = 0;
for(int i = 0; i <= n - 1; ++i)
if(x & (1 << i))//注意做完按位与后的结果不是1,如可能为000010000,所以不要写成x & (1 << i) == 1
cnt++;
return cnt;
}
int main()
{
cin >> n >> m;
//我们在用二进制写题时,下标最好以0开始
for(int i = 0; i <= n - 1; ++i)
cin >> w[i];
//(1 << n) - 1的二进制有n个1
for(int i = 0; i <= (1 << n) - 1; ++i)
{
//如果此时的i的二进制中有n-m个1
if(count_one(i) == n - m)
{
bitset<2010> b;
b[0] = 1;//含义为重量0可以被称出
for(int j = 0; j <= n - 1; ++j)
if(i & (1 << j))//如果i的第j位上是1
b = b | b << w[j];
ans = max(ans,(int)b.count());
}
}
cout << ans - 1 << endl;//把重量为0的情况排除
return 0;
}