背包问题代码模板

01背包

 
 
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long LL;
 
const int MAXN = 1e3 + 5;
int f[MAXN][MAXN];
int a1[MAXN];
int a2[MAXN];
 
int main() {
	int  n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a1[i], &a2[i]);
		
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <=m; j++) {
			f[i][j] = f[i - 1][j];
			if (j >= a1[i])
				f[i][j] = max(f[i][j], f[i-1][j - a1[i]] + a2[i]);
		}
	}
 
	printf("%d\n", f[n][m]);
 
	return 0;
}

完全背包

基础版
 
 
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
 
 
using namespace std;
typedef long long LL;
 
const int N = 1e3 + 5;
int f[N][N];
int a1[N];
int a2[N];
 
int main() {
	int n, v;
	scanf("%d%d", &n, &v);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a1[i], &a2[i]);
	}
 
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= v; j++) {
			for (int k = 0; k * a1[i] <= j; k++) {
				f[i][j] = max(f[i][j], f[i - 1][j - k * a1[i]] + k * a2[i]);
			}
		}
	}
 
	printf("%d\n", f[n][v]);
 
	return 0;
}
 

完全背包优化1

 
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
 
 
using namespace std;
typedef long long LL;
 
const int N = 1e3 + 5;
int f[N][N];
int a1[N];
int a2[N];
 
int main() {
	int n, v;
	scanf("%d%d", &n, &v);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a1[i], &a2[i]);
	}
 
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= v; j++) {
			f[i][j] = f[i - 1][j];
			if (j >= a1[i])
				f[i][j] = max(f[i - 1][j], f[i][j - a1[i]] + a2[i]);
		}
	}
 
	printf("%d\n", f[n][v]);
 
	return 0;
}

完全背包优化成一维数组
 
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
 
 
using namespace std;
typedef long long LL;
 
const int N = 1e3 + 5;
int f[N];
int a1[N];
int a2[N];
 
int main() {
	int n, v;
	scanf("%d%d", &n, &v);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a1[i], &a2[i]);
	}
 
	for (int i = 1; i <= n; i++) {
		for (int j = a1[i]; j <= v; j++) {
			f[j] = max(f[j], f[j - a1[i]] + a2[i]);
			//printf("%d ", f[j]);
		}
		//printf("\n");
	}
 
 
 
	printf("%d\n", f[v]);
 
	return 0;
}
 
 

多重背包  

多重背包(Multiple Knapsack Problem)是背包问题(Knapsack Problem)的一个变体,它是一个经典的组合优化问题。在多重背包问题中,您有一组物品,每个物品都有一个重量、一个价值和一个可用数量限制。您需要在给定一个背包容量的情况下,选择物品以最大化总价值。

与普通背包问题不同,多重背包问题允许您选择多个相同类型的物品,而不仅仅是一个。这意味着您可以在背包中放置多个相同种类的物品,但受到每种物品数量的限制。

基础版

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<queue>

using namespace std;
typedef long long LL;
const int N = 105, V = 105;
int arr[N], brr[N], krr[N],f[N][N];
int n, v;


int main() {
	cin >> n >> v;
	for (int i = 1; i <= n; i++) {
		cin >> arr[i] >> brr[i] >> krr[i];
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= v; j++) {
		    f[i][j]=f[i-1][j];
			for (int k = 1; k <= krr[i]; k++) {
			    if(k*arr[i]<=j)
					f[i][j] = max(f[i][j], f[i - 1][j - k * arr[i]] + k * brr[i]);
			}
		}
	}


	cout << f[n][v] << endl;

	return 0;
}
优化版(二进制优化)

#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>


using namespace std;
typedef long long LL; 
const int N = 5e5 + 5;
int V[N],W[N],f[N];
int n, m;

int main() {
	scanf("%d%d", &n, &m);
	int cnt = 1;
	for (int i = 1, v, w, s; i <= n; i++) {
		scanf("%d%d%d", &v, &w, &s);
		int k = 1;
		while (k <= s) {
			V[cnt] = v * k;
			W[cnt] = w * k;
			cnt++;
			s -= k;
			k *= 2;
		}
		if (s > 0) {
			V[cnt] = v * s;
			W[cnt] = w * s;
			cnt++;
		}
	}
	n = cnt-1;
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= V[i]; j--) {
			f[j] = max(f[j], f[j - V[i]] + W[i]);
		}
	}
	printf("%d\n", f[m]);
	return 0;
}

分组背包

所谓分组背包,即在选择物品的时候,一开始将物品分为好几组,在选择时,可以从每一组中至多选择一件物品,问如何获得最大的价值,所以我们每次可以枚举这个组数,用i表示第几组,用j表示体积,用k来表示选择的物品,伪代码如下

for (int i = 0到组数)
	for (int j = max_v到0)
		for (int k = 此组所有物品)
			f[j] = max (f[j], f[j - v[k]] + w[k])

#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>


using namespace std;
typedef long long LL; 
const int N = 5e2 + 5;
int V[N][N], W[N][N], S[N];
int f[N];
int n, m;

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &S[i]);
		for (int j = 1; j <= S[i]; j++) {
			scanf("%d%d", &V[i][j], &W[i][j]);
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= 0; j--) {
			for (int k = 1; k <= S[i]; k++) {
				if (V[i][k] <= j) {
					f[j] = max(f[j], f[j - V[i][k]] + W[i][k]);
				}
			}
		}
		
	}

	cout << f[m] << endl;
	return 0;
}

混合背包


#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>


using namespace std;
typedef long long LL; 
const int N = 1e3 + 5;
int f[N];
typedef struct st {
	int s, v, w;
}st;
vector<st>p;
int n, m;

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		int s, v, w;
		scanf("%d%d%d", &v, &w, &s);
		if (s < 0)
			p.push_back({ -1,v,w });
		else if (s == 0) {
			p.push_back({ 0,v,w });
		}
		else {
			for (int k = 1; k <= s; k*=2) {
				p.push_back({ -1,v * k,w * k });
				s -= k;
			}
			if (s > 0) {
				p.push_back({ -1,s * v,s * w });
			}
		}
	}
	for (int i = 1; i <= p.size(); i++) {
		if (p[i - 1].s < 0) {
			for (int j = m; j >=p[i-1].v; j--) {
				f[j] = max(f[j], f[j - p[i - 1].v] + p[i - 1].w);
			}
		}
		else {
			for (int j =p[i-1].v; j <= m; j++) {
				f[j] = max(f[j], f[j - p[i - 1].v] + p[i - 1].w);
			}
		}
	}

	printf("%d\n", f[m]);
	return 0;
}

posted @ 2023-06-22 17:30  Landnig_on_Mars  阅读(10)  评论(0编辑  收藏  举报  来源