中途相遇法 解決 超大揹包問題 pack

2021-07-24 16:50:04 字數 1702 閱讀 6018

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種,所以不能直接列舉,但是如果將物品分成...