• 折半搜索


    https://ac.nowcoder.com/acm/contest/889/D(超大背包)

    #include<bits/stdc++.h>
    using namespace std;
    //__
    #define pb push_back
    typedef long long ll;
    typedef unsigned long long ull;
    struct node{
        int num;
        ull sum;
    }a[1<<19],b[1<<19];
    bool cmp(node p,node q){
        return p.sum<q.sum;
    }
    
    int main(){
        int n;
        ull s;
        scanf("%d%llu",&n,&s);
        int lena=1,lenb=1;
        int p=n/2;
        for(int i=0;i<p;i++){
            ull x;
            scanf("%llu",&x);
            int m=lena;
            for(int j=0;j<m;j++){
                a[lena].num=(a[j].num|(1<<i));
                a[lena].sum=a[j].sum+x;
                lena++;
            }
        }
        for(int i=p;i<n;i++){
            ull x;
            scanf("%llu",&x);
            int m=lenb;
            for(int j=0;j<m;j++){
                b[lenb].num=(b[j].num|(1<<i));
                b[lenb].sum=b[j].sum+x;
                lenb++;
            }
        }
        sort(a,a+lena,cmp);
        sort(b,b+lenb,cmp);
        int l=0,r=lenb-1;
        while(l<lena){
            while(a[l].sum+b[r].sum>s&&r)
                r--;
            if(a[l].sum+b[r].sum==s)
                break;
            l++;
        }
        for(int i=0;i<(int)n/2;i++)
            printf("%d",(a[l].num>>i)&1);
        for(int i=int(n/2);i<n;i++)
            printf("%d",(b[r].num>>i)&1);
        return 0;
    }
    View Code

     https://www.luogu.org/problem/SP11469

    题意:在n个数中去若干个数,再把这若干个数分成俩个集合,使这俩个集合的sum相同,问方案数

    分析:n<=20,要是要求全部能取还可以直接用2进制枚举,但他要取若干个,所以考虑把20对半折,直接搜索

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int M=2e6+5;
    vector<int>vis[M];
    map<ll,int>cmp;
    ll yes[M];
    int n,midd,cnt;
    ll a[M];
    void dfs1(int i,int sum,int nowsta){
        if(i>midd){
            if(!cmp[sum])
                cmp[sum]=++cnt;
            vis[cmp[sum]].pb(nowsta);
            return ;
        }
        dfs1(i+1,sum,nowsta);///不取这个数 
        dfs1(i+1,sum+a[i],nowsta|(1<<(i-1)));///把这个数取到第一个集合 
        dfs1(i+1,sum-a[i],nowsta|(1<<(i-1)));///把这个数取到另外的一个集合中 
    }
    void dfs2(int i,int sum,int nowsta){
        if(i>n){
            int x=cmp[sum];
            for(int i=0;i<vis[x].size();i++){
                yes[vis[x][i]|nowsta]=1;
            }
            return ;
        }
        dfs2(i+1,sum,nowsta);
        dfs2(i+1,sum+a[i],nowsta|(1<<(i-1)));
        dfs2(i+1,sum-a[i],nowsta|(1<<(i-1)));
    }
    int main(){
        
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        midd=n/2;
        dfs1(1,0,0);
        dfs2(midd+1,0,0);
        int ans=0;
        for(int i=1;i<(1<<n);i++)
            ans+=yes[i]; 
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    day 23 索引
    day 22 全量更新
    day 21 求贫困户
    day20 函数,同比,和基础
    知识点记录
    day 20试题
    day 16面试题
    day 13拉链数据做存储
    day 13 拉链数据批量处理
    一维,二维,三维数组,vector 初始化
  • 原文地址:https://www.cnblogs.com/starve/p/11360114.html
Copyright © 2020-2023  润新知