2019牛客暑期多校训练营(第九场)-D Knapsack Cryptosystem (折半搜索)

题目链接:https://ac.nowcoder.com/acm/contest/889/D

题意:题意简单,从大小为36的集合中选若干元素使得他们的和为sum。

思路:第一感觉用搜索,复杂度为2^36,需要优化,正好用折半搜索。即在前一半枚举,并用map记录和,枚举后一半时查找是否存在前一半刚好满足两者的和为sum。

AC代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<string>
#include<map>
using namespace std;

typedef long long LL;
int n;
LL sum,a[40];
map<LL,string> mp;

int main(){
    scanf("%d%lld",&n,&sum);
    for(int i=0;i<n;++i)
        scanf("%lld",&a[i]);
    for(int i=0;i<(1<<n/2);++i){
        string s;
        LL tmp=0;
        for(int j=0;j<n/2;++j)
            if((i>>j)&1){
                tmp+=a[j];
                s+='1';
            }
            else{
                s+='0';
            }
        mp[tmp]=s;
    }
    for(int i=0;i<(1<<(n-n/2));++i){
        string s;
        LL tmp=0;
        for(int j=0;j<n-n/2;++j)
            if((i>>j)&1){
                tmp+=a[n/2+j];
                s+='1';
            }
            else{
                s+='0';
            }
        if(mp.count(sum-tmp)){
            cout<<mp[sum-tmp]<<s<<"\n";
            break;
        }
    }
    return 0;
}

 

posted @ 2019-08-15 19:56  Frank__Chen  阅读(145)  评论(0编辑  收藏  举报