zoukankan      html  css  js  c++  java
  • CH2401 送礼物 双向搜索

    双向搜索:把前一半的可行状态搜出来,然后sort+unique,之后搜后一半时,结束时二分一下前一半的答案,拼出一个与W尽量接近的ans来更新

    ps:距LYD说前一半取n/2+2时跑的最快。。。不知,,,

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define R register int
    #define uint unsigned int
    using namespace std;
    inline int g() {
        R ret=0; register char ch; while(!isdigit(ch=getchar()));
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
    } 
    int n,m,hf,w[50];
    uint W,ans,a[(1<<23)+1];
    inline void dfs(int i,uint sum) {
        if(i==hf) {a[++m]=sum; return ;}
        dfs(i+1,sum); if(sum+w[i]<=W) dfs(i+1,sum+w[i]);
    }
    inline void dfs2(int i,uint sum) {
        if(i==n+1) {
            R tmp=upper_bound(a+1,a+m+1,W-sum)-a-1; //cout<<W-sum<<" "<<tmp<<" "<<a[tmp]<<endl;
            ans=max(ans,sum+a[tmp]); return;
        } dfs2(i+1,sum); if(sum+w[i]<=W) dfs2(i+1,sum+w[i]);
    }
    signed main() {
        W=g(),n=g();
        for(R i=1;i<=n;++i) w[i]=g();
        sort(w+1,w+n+1,greater<int>());
        hf=(n>>1)+3; dfs(1,0); sort(a+1,a+m+1); 
        m=unique(a+1,a+m+1)-a-1;
        //for(R i=1;i<=40;++i) cout<<a[i]<<" "; cout<<endl;
        dfs2(hf,0); printf("%d
    ",ans);
    }

    2019.04.26

  • 相关阅读:
    Vasya and Endless Credits CodeForces
    Dreamoon and Strings CodeForces
    Online Meeting CodeForces
    数塔取数 基础dp
    1001 数组中和等于K的数对 1090 3个数和为0
    1091 线段的重叠
    51nod 最小周长
    走格子 51nod
    1289 大鱼吃小鱼
    POJ 1979 Red and Black
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10772515.html
Copyright © 2011-2022 走看看