【题目来源】
https://www.luogu.com.cn/problem/P1441
【题目描述】
现有 n 个砝码,重量分别为 ai,在去掉 m 个砝码后,问最多能称量出多少不同的重量(不包括 0)。
请注意,砝码只能放在其中一边。
【输入格式】
第 1 行为有两个整数 n 和 m,用空格分隔。
第 2 行有 n 个正整数 a1, a2, a3, …, an,表示每个砝码的重量。
【输出格式】
仅包括 1 个整数,为最多能称量出的重量数量。
【输入样例】
3 1
1 2 2
【输出样例】
3
【样例说明】
在去掉一个重量为 2 的砝码后,能称量出 1, 2, 3 共 3 种重量。
【数据规模】
对于 20% 的数据,m=0。
对于 50% 的数据,m≤1。
对于 50% 的数据,n≤10。
对于 100% 的数据,n≤20, m≤4,m<n,ai≤100。
【算法分析】
● 最大可称重量为 n*ai=20*100=2000。
● STL bitset 简介:https://blog.csdn.net/hnjzsyjyj/article/details/148285903
● STL bitset 优化
(1)使用 bitset<2005> 表示可称量重量集合,第 j 位为 1 表示重量 j 可达。
(2)s<<a[i] 表示所有当前可达重量加上砝码 a[i] 后的新重量。
(3)初始化 s[0]=1(重量 0 可达),遍历每个选中的砝码,执行 s|=s<<a[i] 更新可达重量。
(4)s.count()-1 统计非零重量数量。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
int n,m,ans,a[25];
bitset<2005> s;
void dfs(int pos,int cnt,int state){
if(cnt==n-m){
s.reset();
s[0]=1;
for(int i=0;i<n;i++){
if(state & (1<<i)) s|=s<<a[i];
}
ans=max(ans,(int)s.count()-1);
return;
}
if(pos==n) return;
dfs(pos+1,cnt+1,state|(1<<pos)); //Select current weight.
dfs(pos+1,cnt,state); //Don't select weights.
}
int main() {
cin>>n>>m;
for(int i=0; i<n; i++) cin>>a[i];
dfs(0,0,0);
cout<<ans<<endl;
return 0;
}
/*
in:
3 1
1 2 2
out:
3
*/
【参考文献】
https://www.luogu.com.cn/problem/P1441
https://www.luogu.com.cn/problem/P2347
https://www.acwing.com/problem/content/3420/
https://blog.csdn.net/hnjzsyjyj/article/details/148315428
https://blog.csdn.net/hnjzsyjyj/article/details/148285903