• 优化剪枝搜索——牛客多校第二场F


    试了很多种爆搜和剪枝,最后发现还是状压的比较好用

    #include <bits/stdc++.h>
    using namespace std;
    // #define IO
    #define fi first
    #define se second
    #define pb push_back
    #define mk make_pair
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define rep(i,s,t) for(int i=s;i<t;i++)
    #define REP(i,s,t) for(int i=s;i<=t;i++)
    #define DOW(i,s,t) for(int i=s;i>=t;i--)
    #define dow(i,s,t) for(int i=s;i>t;i--)
    #define clr(a,b) memset(a,b,sizeof(a))
    #define debug(x) cout<<#x<<' '<<x<<endl
     
    typedef long long ll;
    typedef pair<int,int>pii;
    inline int lowbit(int x){ return x&(-x); }
    template<typename T>
    inline void read(T&x){
        x=0;int f=1;char ch=getchar();
        while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
        while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
        x*=f;
    }
    const int N = 110;
    ll g[N][N];
    ll n,ans;
     
    void dfs(int mask,int num,int pre,ll preans){
        if(num<<1==n){
            ans=max(ans,preans);return;
        }
        if(n-1-pre+num<n/2)return;       //表示即使是接下来的所有数都选,也不符合条件(集合不能够选够n/2个元素),就直接返回(最优性剪枝)
        for(int i=pre+1;i<n;i++){
            ll nowans=preans;
            rep(j,0,n){
                if(mask&(1<<j))nowans-=g[i][j];
                else nowans+=g[i][j];
            }
            dfs(mask|(1<<i),num+1,i,nowans);
        }
    }
    int main(){
        cin>>n;n<<=1;
        rep(i,0,n) rep(j,0,n) read(g[i][j]);
        ll nowans=0;        //现在将第一个点放到另一个集合中
        rep(i,0,n)nowans+=g[0][i];
        dfs((1<<0),1,0,nowans);
        printf("%lld
    ",ans);
        return 0;
    }

    然后还有一种不同思路的搜索,一开始两个集合都为空,然后往两个集合里填元素,这样会少很多冗余的搜索

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll n,vis[30],mp[30][30],ans;
    
    
    int s1[30],s2[30],top1,top2;
    void dfs(int pos,ll now){
        if(pos>2*n){
            ans=max(ans,now);
            return;
        }
        if(top1<n){
            s1[++top1]=pos;
            ll nxt=now;
            for(int i=1;i<=top2;i++)
                nxt+=mp[pos][s2[i]];
            dfs(pos+1,nxt);
            top1--;
        }
        if(top2<n){
            s2[++top2]=pos;
            ll nxt=now;
            for(int i=1;i<=top1;i++)
                nxt+=mp[pos][s1[i]];
            dfs(pos+1,nxt);
            top2--;
        }
    }
    
    int main(){
        cin>>n;
        for(int i=1;i<=2*n;i++) 
            for(int j=1;j<=2*n;j++)
                scanf("%d",&mp[i][j]);
        ans=0;
        dfs(1,0);
        cout<<ans<<endl;
    }
    /*
    (28,14)=
    */
  • 相关阅读:
    (并查集)小希的迷宫 --HDU -- 1272
    (并查集)Connections in Galaxy War -- zoj --3261 还没写
    (并查集)A Bug's Life -- POJ -- 2492
    LINQ 图解 LINQ学习第三篇 [转]
    C# 4.0 新特性-dynamic 【转】
    C#编程规范
    C#中关于DateTime的最大值和最小值
    .NET,你忘记了么?(八)—— 从dynamic到特性误用 [转]
    C#中dynamic的正确用法【转】
    ASP.NET MVC 中将FormCollection与实体间转换方法【转】
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11287855.html
Copyright © 2020-2023  润新知