description
【題目描述】
蛤布斯有n個物品和乙個大小為m的揹包,每個物品有大小和價值,它希望你幫它求出揹包裡最多能放下多少價值的物品。
【輸入資料】
第一行兩個整數n,m。接下來n行每行兩個整數xi,wi,表示第i個物品的大小和價值。
【輸出資料】
一行乙個整數表示最大價值。
【樣例輸入】
5 100
95 80
4 18
3 11
99 100
2 10
【樣例輸出】
【資料範圍】
對於20%的資料,xi<=1500。
對於另外30%的資料,wi<=1500。
對於100%的資料,n<=40,0<=m<=10^18,0<=xi,wi<=10^15。
中途相遇法這個東西比較有意思.
這題接近於可行的辦法就是暴搜, o(2 ^ n), 但是會炸掉.
不難發現, 假如時間複雜度優化至o(2 ^ (n / 2)), 那麼這題就是可以過的, 因此可以這樣做:
把所有物品分為左右兩半, 2 ^ (n / 2)列舉在同一半中每一種選取物品方案(即從小到大列舉i)所得到的價值以及, 記錄入l[i], r[i]中(通過i的二進位制拆分來得到當前的具體方案).
將l, r排序, 去掉那些空間大而價值小的方案, 掃一遍利用決策單調性即可得到答案.
附上**(跑得好慢…)
#include
#include
#include
using
namespace
std;
const
int maxn = 40;
struct item
item(long
long first, long
long second): size(first), val(second){}
}a[maxn], l[1
<< (maxn >> 1)], r[1
<< (maxn >> 1)];
intoperator
<(item x, item y)
int main()
sort(l, l + (1
<< mid));
long
long cntl = 1;
for(int i = 1; i < 1
<< mid; i ++)
if(l[cntl - 1].val < l[i].val)
l[cntl ++] = l[i];
for(int i = 0; i < 1
<< (n - mid); i ++)
sort(r, r + (1
<< (n - mid)));
long
long cntr = 1;
for(int i = 1; i < 1
<< (n - mid); i ++)
if(r[cntr - 1].val < r[i].val)
r[cntr ++] = r[i];
long
long p = 0, q = cntr - 1;
long
long ans = 0;
for(int p = 0; p < cntl; p ++)
cout
<< ans;
}
超大揹包問題
運用二進位制,折半搜尋,其實我覺得本質就是狀壓思想,列舉前一半所有情況並儲存。然後排序保障總質量越大,價值越大。這裡相當於貪心。可以證明的,如果在一堆一一對應的數裡面,只取乙個,另外乙個數越大才越有可能是最優解。這個思想大概只能用在只取乙個上面。再列舉後半部分。算出每一種列舉方式的總質量,w wi就...
超大揹包問題(01揹包)
超大揹包問題 有n個重量和價值分別為w i 和v i 的物品,從這些物品中挑選總重量不超過w的物品,求所有挑選方案中價值總和的最大值。其中,1 n 40,1 w i v i 10 15,1 w 10 15.這個問題給人的第一感覺就是普通的01揹包。不過,看完資料範圍會發現,這次價值和重量都可以是非常...
超大容量揹包問題
這個問題給人的第一感覺就是普通的01揹包。不過,看完資料範圍會發現,這次價值和重量都可以是非常大的數值,相比之下n比較小。使用dp求解揹包為題的複雜度是o nw 因此不能用來解決這個問題。此時我們應該利用n比較小的特點來尋找其他方法。挑選物品的方案總共有2 n種,所以不能直接列舉,但是如果將物品分成...