• 双向搜索学习笔记


    好像又叫meet in the middle

    所谓双向搜索,简而言之,就是先搜一半,再搜另一半,然后试着将两半拼合。

    具体看例题,你将会有更深的体会。

    例题一:世界冰球锦标赛

    网址:https://www.luogu.com.cn/problem/P4799

    如果洛谷很卡的话,还有一个网址:https://loj.ac/problem/2789

    朴素算法:2^n的搜索

    双向搜索:现将之前的n/2搜出来,排序,再搜后n/2,二分查找。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,m,a[50],ans;
    int s[2000000],tot;
    inline void dfs(int pos,int sum){
        if(sum>m)return;
        if(pos==n/2+1){
            s[++tot]=sum;//记录结果
            return;
        }
        dfs(pos+1,sum);
        dfs(pos+1,sum+a[pos]);
    }
    inline void solve(int pos,int sum){
        if(sum>m)return;
        if(pos==n+1){//二分查找之前有多少个结果加上这个小于等于m
            int l=1,r=tot,rec;
            while(l<=r){
                int mid=(l+r)>>1;
                if(sum+s[mid]<=m){
                    rec=mid;
                    l=mid+1;
                }else r=mid-1;
            }
            ans+=rec;
            //ans+=upper_bound(s+1,s+1+tot,m-sum)-s-1;
            return;
        }
        solve(pos+1,sum);
        solve(pos+1,sum+a[pos]);
    }
    signed main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        dfs(1,0);//预处理前一半
        sort(s+1,s+1+tot);//将预处理的结果排序
        //for(int i=1;i<=tot;i++)
        //    printf("%lld ",s[i]);
        solve(n/2+1,0);//搜索后一半
        printf("%lld
    ",ans);
        return 0;
    } 

     例题二:[USACO12OPEN]Balanced Cow Subsets G

    网址:https://www.luogu.com.cn/problem/P3067

    具体请参照洛谷上的题解,我不知道怎么写,只好给你们转个 链接

    还有代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn=2*1e6+10;
    vector<int>g[maxn];
    map<int,int>p;
    int n,a[maxn],ti;
    inline void dfs(int pos,int sum,int zt){
        if(pos==n/2+1){
            if(!p[sum])p[sum]=++ti;
            g[p[sum]].push_back(zt);
            return;
        }
        dfs(pos+1,sum,zt);
        dfs(pos+1,sum+a[pos],zt|(1<<pos-1));
        dfs(pos+1,sum-a[pos],zt|(1<<pos-1));
    }
    int ans,f[maxn];
    inline void solve(int pos,int sum,int zt){
        if(pos==n+1){
            int x=p[sum];
            for(int i=0;i<g[x].size();i++)
                f[g[x][i]|zt]=1;
            return;
        }
        solve(pos+1,sum,zt);
        solve(pos+1,sum+a[pos],zt|(1<<pos-1));
        solve(pos+1,sum-a[pos],zt|(1<<pos-1));
    }
    signed main(){
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        dfs(1,0,0);
        solve(n/2+1,0,0);
        for(int i=1;i<(1<<n);i++)
            ans+=f[i];
        printf("%lld
    ",ans);
        return 0;
    }

    深深地感到自己的弱小。

  • 相关阅读:
    Educational Codeforces Round 13
    Educational Codeforces Round 12
    vscode 修改标签栏样式为换行全部展示
    webpack uglifyjs 报错 Unexpected token name
    tsconfig.js 使用 paths 设置alias无效问题
    Webpack 报错 filename.indexOf is not a function 的问题
    'GL_EXT_shader_framebuffer_fetch' : extension is not supported
    Flutter命令突然无响应、vscode突然无法连接到IOS模拟器
    解决node fs.writeFile 生成csv 文件乱码问题
    数组map方法与如何使用ES5实现
  • 原文地址:https://www.cnblogs.com/syzf2222/p/12551599.html
Copyright © 2020-2023  润新知