版权声明:来自星空计算机团队——申屠志刚 https://blog.csdn.net/weixin_43272781/article/details/84898638
http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4432
题解:二分折半查询。每种硬币有三种选择:选择其中一个,选择其中两个,不选择。
因此共有3^18 种,对总的方案折半,以其中一半为基础,对另一半二分查询是
否存在可能使得构成k。
#include <stdio.h>
#include <set>
std::set<int> st1, st2;
int a[20];
void dfs(int R, int id, int sum, std::set<int> &st){
if (id == R){
st.insert(sum);
return;
}
dfs(R, id+1, sum, st);
dfs(R, id+1, sum+a[id], st);
dfs(R, id+1, sum+2*a[id], st);
}
bool check(int K){
for(std::set<int> ::iterator it = st1.begin(); it != st1.end(); it ++){
if(st2.find(K-*it) == st2.end()) continue;
return true;
}
return false;
}
int main(){
// freopen("baby_coins.in", "r", stdin);
// freopen("baby_coins.out", "w", stdout);
int T, n, K;
int ica = 1;
scanf("%d", &T);
while(T --){
scanf("%d%d", &n, &K);
for(int i = 0; i < n; i ++){
scanf("%d", &a[i]);
}
int ok = false;
if(n == 1){
if(a[0] == K || a[0]*2 == K) ok = 1;
}else{
dfs(n/2, 0, 0, st1);
dfs(n, n/2, 0, st2);
ok = check(K);
}
printf("Case %d: %s\n", ica ++, ok ? "Yes":"No");
st1.clear();
st2.clear();
}
return 0;
}