2401 送礼物 (双向搜索)

【题目描述】

	作为惩罚,GY被遣送去帮助某神牛给女生送礼物(GY:貌似是个好差事)但是在GY看到礼物之后,他就不这么认为了。某神牛有N个礼物,且异常沉重,但是GY的力气也异常的大(-_-b),他一次可以搬动重量和在w(w<=2^31-1)以下的任意多个物品。GY希望一次搬掉尽量重的一些物品,请你告诉他在他的力气范围内一次性能搬动的最大重量是多少。

【题目链接】

2401 送礼物

【算法】

双向搜索,把礼物按重量分成两部分。第一次搜索记录下后一半礼物可能达到的重量,第二次搜索对前一部分礼物可能达到的重量加上之前记录的重量取小于W的最大值即可。

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll w,n,tot,ans;
ll a[50],rec[100010000];
void dfs1(ll x,ll val) {
    if(x>n) {
        rec[++tot]=val;
        return;
    }
    if(val+a[x]<=w) dfs1(x+1,val+a[x]);
    dfs1(x+1,val);
}
void dfs2(ll x,ll val) {
    if(x>=(n+1)>>1) {
        int l=1,r=tot;
        while(l<r) {
            int mid=(l+r+1)>>1;
            if(rec[mid]+val<=w) l=mid;
            else r=mid-1;
        }
        ans=max(ans,val+rec[l]);
        return;
    }
    if(val+a[x]<=w) dfs2(x+1,val+a[x]);
    dfs2(x+1,val);
}
int main() {
    scanf("%I64d%I64d",&w,&n);
    for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
    sort(a+1,a+n+1);
    dfs1((n+1)/2,0);
    sort(rec+1,rec+1+tot);
    dfs2(1,0);
    printf("%I64d\n",ans);
    return 0;
}

posted @ 2018-08-24 11:09  飞飞翔滴少年  阅读(383)  评论(0编辑  收藏  举报