有n件物品和乙個容量為v 的揹包。放入第\(i\)件物品耗費的空間是\(c_i\),得到的價值是\(w_i\)。求解將哪些物品裝入揹包可使價值總和最大。
這是最基礎的揹包問題,特點是:每種物品僅有一件,可以選擇放或不放。 用子問題定義狀態:即\(f[i,v]\)表示前i件物品恰放入乙個容量為v的揹包可以獲得的最大價值。則其狀態轉移方程便是:
\(f_ = \max\, f_ + w_i\}\)
memset(f[0], 0, sizeof(f[0]));
for (int i = 1; i <= n; ++i)
}for (int i = 0; i <= v; ++i) ans = max(ans, f[n][i]);
其時間複雜度和空間複雜度都是\(o(nv)\), 其中時間複雜度基本上不能再優化了,但空間複雜度卻可以優化到\(o(v)\)。
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; ++i)
}for (int i = 0; i <= v; ++i) ans = max(ans, f[i]);
看一道題:小a點菜
對於這類改變問法的問題,一般只需將狀態轉移方程中的\(max\)改成\(sum\)即可。例如若每件物品均是完全揹包中的物品,轉移方程即為
\(f[i,v] = sum\\)
初始條件是\(f[0,0] = 1\)。
f[0][0] = 1;
for (int i = 1; i <= n; ++i)
}ans = f[n][v];
printf("%d\n", ans);
再看一題:裝箱問題 [noip2001普及組第4題]
其實這裡\(w_i\)就是\(c_i\)。
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; ++i)
}for (int i = 0; i <= v; ++i) ans = max(ans, f[i]);
printf("%d\n", v - ans);
又來一題:積木城堡
求出每個高度的城堡數量。
for (int i = 0; i < n; ++i)
if (max_sum < sum) max_sum = sum;
memset(f, 0, sizeof(f));
f[0] = 1;
for (int j = 1; j <= np; ++j)
} }}
C 0 1揹包問題
0 1揹包問題 0 1揹包問題基本思想 p i,j 表示在前面i個物品總價值為j時的價值最大值。str i,j 表示在前面i個物品總價值為j時的價值最大值時的物品重量串。i 0 或者j 0時 p i,j 0 str i,j 第i件物品的在重量小於j時能夠放入揹包 p i,j p i 1,j w i ...
C 01揹包問題
01揹包問題 有n個重量和價值分別為wi,vi的物品。從這些物品中挑選出總重量不超過w的物品,求所有挑選方案中價值總和的最大值 輸入格式 nw v w輸出格式 價值總和最大值 輸入 42 3 1 23 4 2 25 輸出 7解題思路 對每個物品有兩種選擇,選或者不選。選擇該物品的話,總價值會增加,剩...
揹包問題詳解(c ) 01揹包
有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i件物品的體積是 v,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。第一行兩個整數 n,v用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 vi,wi用空格...