1. 程式人生 > 其它 >珍惜現在,感恩生活(多重揹包)

珍惜現在,感恩生活(多重揹包)

貪心策略——多重揹包

題目

Problem Description

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

人生是一個充滿了變數的生命過程,天災、人禍、病痛是我們生命歷程中不可預知的威脅。
月有陰晴圓缺,人有旦夕禍福,未來對於我們而言是一個未知數。那麼,我們要做的就應該是珍惜現在,感恩生活——
感謝父母,他們給予我們生命,撫養我們成人;
感謝老師,他們授給我們知識,教我們做人
感謝朋友,他們讓我們感受到世界的溫暖;
感謝對手,他們令我們不斷進取、努力。
同樣,我們也要感謝痛苦與艱辛帶給我們的財富~

Input

輸入資料首先包含一個正整數C,表示有C組測試用例,每組測試用例的第一行是兩個整數n和m(1<=n<=100, 1<=m<=100),分別表示經費的金額和大米的種類,然後是m行資料,每行包含3個數p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分別表示每袋的價格、每袋的重量以及對應種類大米的袋數。

Output

對於每組測試資料,請輸出能夠購買大米的最多重量,你可以假設經費買不光所有的大米,並且經費你可以不用完。每個例項的輸出佔一行。

Sample Input

1
8 2
2 100 4
4 100 2

Sample Output

400

分析

0-1揹包:每種物品只有一個

完全揹包:每種物品有無限個

多重揹包:每種物品有有限個。針對每個物品有c個,需要將它以二進位制的方式分解(都是碼農了,不要分成1、2、3......,太low了~),c = 20+21+22+...+2c-1+(c-2c+1)

解答

/*
-------------------------------------------------
   Author:       wry
   date:         2022/3/5 17:05
   Description:  bag
-------------------------------------------------
*/ #include <bits/stdc++.h> using namespace std; const int MAXN = 1000+10; int weight[MAXN][MAXN]; //總價值 int everyWeight[MAXN]; int everyPrice[MAXN]; int main() { int CaseNumber; cin >> CaseNumber; while (CaseNumber--) { memset(weight,0,sizeof(weight)); int n,m; //n表示總經費,m表示種數 cin >> n >> m; int j = 1; for (int i=1;i<=m;i++){ int p,h,c; //每袋大米價格(上限),每袋大米質量(追求最大),此種類大米袋數 cin >> p >> h >> c; //根據袋數分解 int k=0; while (c>=pow(2,k)) { c -= pow(2,k); everyPrice[j] = pow(2,k) * p; everyWeight[j] = pow(2,k) * h; j++; k++; } if (c!=0) { everyPrice[j] = c*p; everyWeight[j] = c*h; j++; } } //同0-1揹包(注意這裡是價格有上限,尋求重量最大值) for (int i=1;i<=j-1;i++) { for (int t=1;t<=n;t++) { if (t<everyPrice[i]) { weight[i][t] = weight[i-1][t]; } else { weight[i][t] = max(weight[i-1][t],weight[i-1][t-everyPrice[i]]+everyWeight[i]); } } } cout << weight[j-1][n] << endl; } return 0; }