日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

送礼物(双向搜索)

發(fā)布時間:2024/9/5 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 送礼物(双向搜索) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

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

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

輸入格式

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

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

輸出格式

僅一個整數,表示達達在他的力氣范圍內一次性能搬動的最大重量。


emmmmm, 爆搜的話直接進行指數型枚舉——枚舉每個物品選還是不選, 時間復雜度為O(2n)。當然,若搜索過程中已選的禮物重量之和大于w, 可以及時剪枝。此題n <= 45 復雜度過高, 我們可以采取雙向搜索, 把禮物分成兩半。

首先,我們搜索出前一半禮物選出若干個, 可能到達0-w之間的所有重量值, 放在一個數組里, 對數組進行排序, 去重。

然后, 我們進行第二波搜索, 嘗試從后一半禮物中選出一些。對于每個可能達到的重量t,從第一部分得到的數組中二分查找<= w - t的數組中最大的一個, 用兩者的和更新答案

ps:取1 - n / 2 + 2 作為前一半, n / 2 + 3 - n為后一半, 搜索速度更快;

#include <bits/stdc++.h>using namespace std;typedef long long ll; const int INF = 0x3f3f3f3f; const int MAXN = 2e7 + 100; const int MAXM = 3e3 + 10;template < typename T > inline void read(T &x) {x = 0; T ff = 1, ch = getchar();while(!isdigit(ch)) {if(ch == '-') ff = -1;ch = getchar();}while(isdigit(ch)) {x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}x *= ff; }template < typename T > inline void write(T x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0'); }ll w, n, top = 0, tot = 0, ans, a[MAXN], b[MAXN], c[MAXN];inline bool cmp(ll x, ll y) {return x > y; }ll find(ll x) {int l = 1, r = tot;while(l < r) {int mid = (l + r + 1) / 2;if(c[mid] <= x) l = mid;else r = mid - 1;}return c[l]; } void dfs(ll x, ll val) {if(x == n / 2 + 3) {b[++top] = val;return ;} if(val + a[x] <= w) dfs(x + 1, val + a[x]);dfs(x + 1, val); }void DFS(ll x, ll val) {if(x == n + 1) {ll u = find(w - val);ans = max(ans, u + val);return ;}if(val + a[x] <= w) DFS(x + 1, val + a[x]);DFS(x + 1, val); }int main() {read(w); read(n);for(int i = 1; i <= n; ++i)read(a[i]);sort(a + 1, a + n + 1,cmp);dfs(1, 0);sort(b + 1, b + top + 1);c[++tot] = 0;for(int i = 1; i <= top; ++i) {if(b[i] != b[i - 1]) c[++tot] = b[i];}DFS(n / 2 + 3, 0);write(ans);return 0; }

?

轉載于:https://www.cnblogs.com/AK-ls/p/11276734.html

總結

以上是生活随笔為你收集整理的送礼物(双向搜索)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。