Baby Coins

版权声明:来自星空计算机团队——申屠志刚 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43272781/article/details/84898638
今日推荐