完全揹包 && 多重揹包

完全揹包

Description

有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。第i種物品的體積是v[i],價值是p[i]。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。

Input

第一行兩個整數爲V和N
以下N行,每行兩個整數爲v[i]和p[i]

Output

體積總和不超過揹包容量價值最大值

Sample Input Copy

10 4
2 1
3 3
4 5
7 9

Sample Output Copy

12

HINT

N<=100
V<=1000

多重揹包

Description

一個揹包,承量有限爲W,有n種物體,第i種物體,價值Vi,佔用重量爲 Wi,且有Ci件,選擇物品若干放入揹包,使得總重量不超過揹包的承重。總價值最大?

Input

第1行,2個整數,N和W中間用空格隔開。N爲物品的種類,W爲揹包的容量。(1 <= N <= 500,1 <= W <= 6000) 第2 - N + 1行,每行3個整數,Wi,Pi和Ci分別是物品體積、價值和數量。(1 <= Wi<=100, Pi <= 1000, 1 <= Ci <= 10)

Output

輸出可以容納的最大價值

Sample Input Copy

5 1000

80 20 4

40 50 9

30 50 7

20 30 6

20 20 1

Sample Output Copy

1060

分析
對於完全揹包以及多重揹包的講述,之前也寫過一篇blog,其中的多是優化過的,但是博主對優化的過程卻總是一知半解,這裏邊用一些相對暴力但是更便於記憶推到理解的方法
首先是完全揹包,在這之前,前面有過1篇對完全揹包填充方案計數的blog,有意的者可以去翻看
https://blog.csdn.net/c_uizrp_dzjopkl/article/details/99605716
這裏便不多贅述了,畢竟是相同的原理
與其的不同便是要算出最大的價值,所以動態轉移方程便變成了max的比較,也就是打擂臺
對於不放和放了的可得的價值的打擂臺
f[n][m] = max(f[n-1][m],f[n-1][m-w[n]*k]+v[n]*k) (w[n]表示第n個物品的重量,v[n]表示第n個物品的價值,k表示第n個物品放幾個)
循環的過程也是一樣的
之後便是初始化了
不同於之前的是我們在這裏要把價值給帶上
也就是 f[1][j] = j/w[1]*v[1];
但是我們不用對0列進行初始化了,因爲我們是用不到的

之後便是多重揹包了
對於物品的裝放,我們需要在 c[i] 和 m/w[i] 之間比較,取較小值
因爲一種物品如果要放那麼其質量不可以超過 m 所以一種物品,如果可以,我們就全放不然的話就放當前最多的數量,都使利益儘量最大

代碼
完全揹包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <math.h>
#include <stdio.h>
#include <queue>
#include <stack>
#include <vector>
using namespace std;

int f[1009][1009],w[1009],v[1009];
int n,m;

int main() {
	scanf("%d %d",&m,&n);
	for (int i = 1; i <= n; i++) scanf("%d %d",&w[i],&v[i]);
	
	for (int j = 1; j <= m; j++) f[1][j] = j/w[1]*v[1]; 
		
	for (int i = 2; i <= n; i++)
		for (int j = 1; j <= m; j++)
			for (int k = 0; k <= j/w[i]; k++)
				f[i][j] = max(f[i][j],f[i-1][j-w[i]*k]+k*v[i]);
	
	printf("%d",f[n][m]); 
	
	return 0;
}

多重揹包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
using namespace std;

long long f[1009][6009],w[1009],v[1009],num[1009];
int n,m;

int main() {
	scanf("%d %d",&n,&m);
	for (int i = 1; i <= n; i++) scanf("%d %d %d",&w[i],&v[i],&num[i]);
	
	for (int j = 1; j <= m; j++) f[1][j] = min(j/w[1],num[1])*v[1];
	
	for (int i = 2; i <= n; i++)
		for (int j = 1; j <= m; j++)
			for (int k = 0; k <= min(j/w[i],num[i]); k++)
				f[i][j] = max(f[i][j],f[i-1][j-w[i]*k]+v[i]*k);
		
	printf("%lld",f[n][m]);
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章