有 n
nn 個重量和價值分別為 w
iw_i
wi 和 v
iv_i
vi 的物品。從這些物品中挑選出總重量不超過 w
ww 的物品放入揹包中,求揹包裡物品價值總和的最大值。
n wv
1w1v
2w2.
....
.vnw
nn\space w \\ v_1\space w_1\\ v_2\space w_2 \\ ......\\ v_n\space w_n
nwv1w
1v2
w2
....
..vn
wn
輸出揹包裡物品價值總和的最大值
4 51≤n4 25 2
2 18 3
≤40
1 ≤ n ≤ 40
1≤n≤40
1 ≤v
i≤10
151 ≤ v_i ≤ 10^
1≤vi≤
1015
1 ≤w
i≤10
151 ≤ w_i ≤ 10^
1≤wi≤
1015
1 ≤w
≤1015
1 ≤ w ≤ 10^
1≤w≤10
15還以為又能水一道揹包模板,沒想到啊
其實這道題的突破點很明顯,我們可以看到n≤40
n \leq 40
n≤40
,不難想到用暴力**
但如果直接暴力,複雜度為o(2
n)
o(2^n)
o(2n
),就算加上剪枝還是只有70分
那不就過不了了嗎
所以,為了優化這個複雜度,我們想到分治
我們可以將n
nn拆成兩半後再列舉,這樣複雜度就變成了兩個2n/
22^
2n/2
,具有可行性,這樣就可以將問題轉化為在前半找到質量和價值為w1,
v1
w_1,v_1
w1,v1
後,在後半部分找w
2w_2
w2使在w1+
w2≤w
w_1+w_2 \leq w
w1+w2
≤w時v
2v_2
v2的最大值
現在要考慮的問題就成了如何在所有(w2
,v2)
(w_2,v_2)
(w2,v
2)高效的找到這個滿足條件的最大的v
2v_2
v2這有些像我們當時學二分答案的樣子了,所以我們想到將這個集合排序並去除明顯的非最優解
明顯的非最優解值(wi
,vi)
(w_i,v_i)
(wi,v
i)是指存在乙個(wj
,vj)
(w_j,v_j)
(wj,v
j)使wj≤
wi&&
vj≥v
iw_j \leq w_i \space \space \&\& \space \space v_j \geq v_i
wj≤wi
&&v
j≥v
i這樣去掉後就是乙個簡單的二分搜尋了
#include
#include
#include
#define max_n 40
using
namespace std;
long
long inf =
0x3f3f3f3f3f3f3f3fll
;//設為 (1<<20) 也可以
pair<
long
long
,long
long
> ps[
1<<
(max_n /2)
];//(重量,價值)
intmain()
} ps[i]
=make_pair
(sw, sv);}
//去除多餘的元素: sw[i] <= sw[j] 並且 sv[i] >= sv[j]
sort
(ps, ps +(1
<< n2));
int m =1;
for(
int i =
1; i <
1<< n2; i++)if
(ps[m -1]
.second < ps[i]
.second)
ps[m++
]= ps[i]
;//列舉後半部分 o(2^n/2)並求解
long
long res =
0ll;
for(
int i =
0; i <
1<<
(n - n2)
; i++)}
if(sw <= w)
}printf
("%lld\n"
, res)
;fclose
(stdin);
fclose
(stdout);
return0;
}
超大揹包問題解題報告
超大揹包問題 有重量和價值分別為wi和vi的n個物品,從這些物品中挑選總重量不超過w的物品,求所有挑選方案中價值總和最大值 限制條件 1 n 40 1 wi,vi 10 15 1 w 10 15 分析 由於本題w巨大,因此是一道假動態規劃題,如果用動態規劃要麼爆空間要麼超時,於是我們可以抓住n極小的...
超大揹包問題
運用二進位制,折半搜尋,其實我覺得本質就是狀壓思想,列舉前一半所有情況並儲存。然後排序保障總質量越大,價值越大。這裡相當於貪心。可以證明的,如果在一堆一一對應的數裡面,只取乙個,另外乙個數越大才越有可能是最優解。這個思想大概只能用在只取乙個上面。再列舉後半部分。算出每一種列舉方式的總質量,w wi就...
超大揹包問題(01揹包)
超大揹包問題 有n個重量和價值分別為w i 和v i 的物品,從這些物品中挑選總重量不超過w的物品,求所有挑選方案中價值總和的最大值。其中,1 n 40,1 w i v i 10 15,1 w 10 15.這個問題給人的第一感覺就是普通的01揹包。不過,看完資料範圍會發現,這次價值和重量都可以是非常...