完全揹包 && 多重揹包

完全揹包

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章