題目描述
終於,破解了千年的難題。小 ff 找到了王室的寶物室,裡面堆滿了無數價值連城的寶物。
這下小 ff 可發財了,嘎嘎。但是這裡的寶物實在是太多了,小 ff 的採集車似乎裝不下那麼多寶物。看來小 ff 只能含淚捨棄其中的一部分寶物了。
小 ff 對洞穴裡的寶物進行了整理,他發現每樣寶物都有一件或者多件。他粗略估算了下每樣寶物的價值,之後開始了寶物篩選工作:小 ff 有乙個最大載重為w的採集車,洞穴裡總共有n種寶物,每種寶物的價值為vi,重量為wi,每種寶物有mi件。小 ff 希望在採集車不超載的前提下,選擇一些寶物裝進採集車,使得它們的價值和最大。
輸入格式
第一行為乙個整數n和w,分別表示寶物種數和採集車的最大載重。接下來n行每行三個整數vi,wi,mi。
輸出格式
輸出僅乙個整數,表示在採集車不超載的情況下收集的寶物的最大價值。
輸入輸出樣例
輸入:4203935
9194
2813
輸出:27
下面就是這道題的題解!
這道題好像就是多重揹包
多重揹包有很多種思路去做,我會的一共有兩種:
第一種是把多重揹包看成是01揹包來做
就直接說這個題,每種寶物有乙個或者多個,我們可以把這多個看成是不同的物體,這樣就是乙個普通的01揹包問題
但是嘞,這麼做時間複雜度會暴增,肯定會爆掉幾個點所以這個問題就不能用這個方法去做
所以直接進入下個方法:
這個方法用到了二進位制的思想
怎麼碩呢
舉個例子,乙個數13,有這麼幾個數:1,2,4,8,16...(我絕對不會告訴你這是以2為底數的冪)
要求用這些數湊齊13,很簡單1+4+8=13,
其他的任何正整數都可以湊出來,為什麼呢?
把這些以2為底數的冪全部用2進製表示:
1->1
2->10
4->100
8->1000
然後來湊數x
x用二進位制來表示肯定是1和0組成的,然後看上面的數,每乙個以2為底數的冪都在每個二進位制位上有乙個單獨的1,其他都是0
也就是說,所有1和0的組合都能夠加出來
所以,以2為底數的冪相加可以湊出任何乙個正整數。
好了,證明完了,現在做題
在這個題目中,我們可以不把寶物數量分成乙個乙個的,而是分成上面所說的數字
這樣時間複雜度會大大降低。
下面直接上**(資料很水,這種非最優方法就能過)
#include#include#include
#include
#include
#define inf 100000000
using
namespace
std;
//狀態:dp[i][j]表示前i個物品占用體積為j時所獲得的的最大價值。
//轉移方程:dp[i][j]=max(dp[i-1][j]
//dp[i-1][j-w[i]]+v[i]
//........
//dp[i-1][j-n[i]*w[i]]+n[i]*v[i])
//複雜度:o(σlogn[i]*m)
int n0,v0,w0,v[100001],w[100001],dp[1001][1001
]; int
main()
if(n0!=0
)
}for(int i=1;i<=d;i++)
for(int j=v;j>=0;j--)
int ans=0
;
for(int i=0;i<=v;i++)
cout
}
最後祝大家ac所有題!
給個贊再走唄?
洛谷P1776 寶物篩選
當年在tb桌前跪著聽懂了單調佇列優化多重揹包 然後那天下午codevs上的多重揹包一直過不去 現在codevs沒了,時間過得真快,有點心酸,當年bzoj也不知道,全在codevs上做題,好多 記錄都沒了。今天突然發現這題補掉,舒服了 includeusing namespace std const ...
洛谷p1776寶物篩選
寶物篩選 多重揹包問題 物品數目已知 可以列舉每個物品 當做01揹包來做 不過會超時 此時需要二進位制拆分來優化 分解成新的物品 再跑一遍01揹包即可 二進位制拆分 01揹包 設f j 表示前i件物品花費恰好為j的最大價值 include include using namespace std co...
洛谷P1776 寶物篩選
題目大意 n種物品,揹包有容量w。現在每個物品價值p,重量v,數量k,求揹包能放物品的最大價值。解題思路 多重揹包問題。然而貌似直接列舉k是會超時的,所以需要加上優化。我們把每個k拆成 2 0 2 1 2 2 2 n x 的形式,然後進行揹包。容易知道,這樣拆分出的物品能保證選取其中若干個相加可以的...