hdu2191多重揹包單調佇列優化

2022-02-27 09:02:29 字數 1274 閱讀 4439

模板,果然dp還是要從零開始補/kk

樸素方法,用 \(f(i,j)\) 表示考慮前 \(i\) 個物品,\(j\) 元錢最多能獲得多少價值,下面用 \(n\) 表示物品種類數,\(m\) 表示總錢數

\(f(i,j)=\max(f(i-1,j-k\cdot w_i)+k\cdot v_i),k\le num_i\)

換一種形式,因為是 \(k\cdot w_i\),所以嘗試考慮以下 \(j\) 除以 \(w_i\) 的餘數,也就是令 \(d=j\bmod w_i\)

\(f(i,j)=\max(f(i-1,d+k\cdot w_i)+(num_i-k)\cdot v_i)\)

其實就是選了 \(num_i-k\) 個這種物品,再整理一下就是

\(f(i,j)=\max(f(i-1,d+k\cdot w_i)-k\cdot v_i)+num_i\cdot v_i\)

所以就可以對於每乙個物品,列舉每個 \(d\),用單調佇列維護一下

對於每個 \(d\),列舉 \(k\) 滿足 \(d+k\cdot w_i\le m\)

單調佇列操作:然後把 \(f(i-1,d+w_i\cdot k)\) 入隊同時彈出所有比他小的,把所以的 \(k',k-k'都出隊,因為它們已經不滿足此物品個數的要求

用單調佇列的性質取乙個最大值和 \(f(i,d+k\cdot w_i)\) 來去 \(\max\) 就行了

\(d\le w-1,k\le \dfrac\)

所以沒做一次單調佇列的迴圈次數就是

\[\sum_^\dfrac=\dfrac^m-d}=\dfrac^}=\dfrac=m-0.5w+1

\]也就是 \(o(m)\),希望沒有假,在複雜度這還卡了一會

所以總複雜度是 \(o(nm)\)

#include#include#include#include#include#include#include#define reg register

#define en std::puts("")

#define ll long long

inline int read()

while(c>='0'&&c<='9')

return y?x:-x;

}int f[105][105];

int num[2005],ind[2005],tail,head;

int n,m;

int main()

} }std::printf("%d\n",f[n][m]);

} return 0;

}

hdu2191多重揹包單調佇列優化

多重揹包單調佇列優化 dp c i p max dp c k p i k h 每種揹包的容量p,價值h,c的範圍為0 p 1,i和k的範圍為0 num 能夠取的揹包的數量 揹包的取法可以看做是劃分為0 p 1這p個容量再加上i個揹包。dp c i p dp c k p k h i h include...

hdu 2191 多重揹包的單調佇列優化

多重揹包單調佇列優化是思想是。普通的dp為 dp i j max 其實你可以發現對能更新j是j和乙個剩餘類。也就是 0,v i 2v i 3v i 4v i 1 1 v i 1 2v i 1 3v i v i 1,2 v i 1.更新值存在乙個剩餘類中,組與組之間不存在更新。那麼實際上我們可以寫dp...

HDU 2191 多重揹包

problem description 急!災區的食物依然短缺!為了挽救災區同胞的生命,心繫災區同胞的你準備自己採購一些糧食支援災區,現在假設你一共有資金n元,而市場有m種大公尺,每種大公尺都是袋裝產品,其 不等,並且只能整袋購買。請問 你用有限的資金最多能採購多少公斤糧食呢?後記 人生是乙個充滿了...