1. 程式人生 > 實用技巧 >送禮物(雙向DFS)

送禮物(雙向DFS)

達達幫翰翰給女生送禮物,翰翰一共準備了N個禮物,其中第i個禮物的重量是G[i]。

達達的力氣很大,他一次可以搬動重量之和不超過W的任意多個物品。

達達希望一次搬掉儘量重的一些物品,請你告訴達達在他的力氣範圍內一次效能搬動的最大重量是多少。

輸入格式
第一行兩個整數,分別代表W和N。

以後N行,每行一個正整數表示G[i]。

輸出格式
僅一個整數,表示達達在他的力氣範圍內一次效能搬動的最大重量。

資料範圍
1≤N≤46,
1≤W,G[i]≤231−1
輸入樣例:
20 5
7
5
4
18
1
輸出樣例:
19


#include <iostream>
#include<algorithm>
#include <cstring>
using namespace std;
const int N = 46;
typedef long long LL;
int k ,cnt;
int w[1 << 25];
int n , m ;
int p[N];
int ans;
void dfs1(int u ,int s)
{
    if(u == k)
    {
        w[cnt++] = s;
        return ;
    }
    
    dfs1(u+1,s);
    
    if((LL)s + p[u] <= m) dfs1(u + 1, s + p[u]);
    
}

void dfs2(int u , int s)
{
    if(u >= n)
    {
        int l  = 0 , r = cnt - 1;
        
        while(l < r)
        {
            int mid = l + r + 1>> 1;
            if((LL)s + w[mid] <= m)l = mid;
            else r = mid -1;
        }
        ans = max(ans,s + w[l]);
        return ;
    }
    dfs2(u+1,s);
    if((LL) s + p[u] <= m) dfs2(u +1,s + p[u]);
}

int main()
{
    cin >> m>>n;
    for(int i = 0 ; i < n ;  i++) cin >> p[i];
    
     k = n /2 + 2;
    
    sort(p,p+n);
    reverse(p,p+n);
    
    dfs1(0,0);
    
    sort(w,w+cnt);
    cnt = unique(w,w+cnt)-w;
    
    dfs2(k,0);
    
    cout << ans ;
    
    return 0;
}