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\n",ans);
}

2019.04.26

posted @ 2019-04-26 09:43  LuitaryiJack  阅读(147)  评论(0编辑  收藏  举报