用單調佇列處理多重揹包

2021-07-29 18:28:35 字數 1319 閱讀 5638

有n種物品,每種物品的數量為c1,c2……cn。從中任選若干件放在容量為w的揹包裡,每種物品的體積為w1,w2……wn(wi為整數),與之相對應的價值為p1,p2……pn(pi為整數)。求揹包能夠容納的最大價值。

input

第1行,2個整數,n和w中間用空格隔開。n為物品的種類,w為揹包的容量。(1 <= n <= 100,1 <= w <= 50000)

第2 - n + 1行,每行3個整數,wi,pi和ci分別是物品體積、價值和數量。(1 <= wi, pi <= 10000, 1 <= ci <= 200)

output

輸出可以容納的最大價值。

input示例

3 6

2 2 5

3 3 8

1 4 1

output示例

9對於樸素的做法,方程式為:

f[j]=max

我們希望可以用單調性來解決問題,那麼就要讓max中的值變為「定值+對於某乙個時刻,這乙個區間要加的值一樣」這樣的形式,那麼我們考慮拆一下方程式

f[j]=max+a *v

在化成這樣的形式之後,我們可以儲存每乙個f[j-(a-k)*v]-k *v,並且保證他們的單調性就可以了

我們考慮具體的實現

w為可以放的空間大小,v為當前物品的所需空間,p為價值,c為最多放的個數,當前放了k的空間

設d=k%v,j=k/v 則有 k=j*v+d

那麼我們可以轉化一下原方程

f[j*v+d]=max+j *p

此時我們維護一下max裡面括著的那一段的單調性就好了

具體的維護方法:

1:我們現在新插入乙個數,則從後面往前刪,直到找到乙個比當前插入數大的數

2:如果當前隊頭對應的對於第i種數取的個數已經大於c了,那麼l++

3:更新當前的f[k]

在程式中:

首先列舉第一維i表示現在做第i種物品

然後依次列舉餘數d,清空佇列,個數j

然後就是上述三步

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxm=100005;

int f[maxm],a[maxm],b[maxm];

int i,j,k,l,r,n,w,d,ans,v,p,c;

void addin(int x,int y)

int main()

單調佇列優化多重揹包

多重揹包的最原始的狀態轉移方程 令 c i min num i j v i f i j max f i 1 j k v i k w i 1 k c i 這裡的 k 是指取第 i 種物品 k 件。如果令 a j v i b j v i 那麼 j a v i b.這裡用 k 表示的意義改變,k 表示取第...

單調佇列優化多重揹包

多重揹包 n個物品,揹包承重m,每個物品 重量 wi 價值vi 個數為ci 普通多重揹包複雜度 o nmc for int i 1 i n i for int j 1 j m j for int k 1 k c i k w i j k f i j max f i j f i 1 j k w i k ...

單調佇列優化多重揹包

應該是個經典演算法,稍微記錄一下 用 w i 表示重量,v i 表示價值 那麼不難寫出轉移方程 f i j max f i 1 j k w i k v i 考慮用單調佇列優化。我們若要用單調佇列優化,那麼必須滿足轉移時所需要的狀態只與 k 有關 這裡要用到乙個神仙操作,對 j w i 分類 因為對於...