01背包

01背包

N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

i 件物品的体积是 vi,价值是 wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式
第一行两个整数,NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V1000
0<vi,wi1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
8

题意

给出n个有体积有价值的物品,任意选取物品组合使得在背包容量有限条件下(m)总价值最大

特点

  1. 每个物品只能选一次
  2. 取最大值

dfs

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

#define X first
#define Y second

typedef pair<int,int> pii;
typedef long long LL;
const char nl = '\n';
const int N = 1010;
int n,m,V,W,cnt;
int v[N],w[N],ans[N];


void dfs(int x){
	if(x > n){
		ans[++cnt] = W;
		return;
	}

	if(V >= v[x]){   //选(注意是>=而不是>)
		V -= v[x];
		W += w[x];
		dfs(x + 1); 
		V += v[x];
	    W -= w[x];
	}
	dfs(x + 1);	//不选

}

void solve(){
	cin >> n >> m;
	V = m;
	for(int i = 1; i <= n; i ++)cin >> v[i] >> w[i];
	dfs(1);
	int res = 0;
	for(int i = 1; i <= cnt; i ++)res = max(res,ans[i]);
	cout << res;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);

	solve();
}

结果: Segmentation Fault
通过了 4/12个数据
原因:在程序运行过程中,如果递归调用的层数过多,会因为系统分配的栈空间溢出引发错误 -> 递归改成递推
许多步骤重复计算了!!! -> 记忆化搜索完善

dp

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

#define X first
#define Y second

typedef pair<int,int> pii;
typedef long long LL;
const char nl = '\n';
const int N = 1010;
int n,m;
int v[N],w[N],f[N][N];
//f[i][j]记录剩余容积为i时选前j个物品的最大值

void solve(){
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)cin >> v[i] >> w[i];
	for(int i = 1; i <= m; i ++){
		for(int j = 1; j <= n; j ++){
			f[i][j] = f[i][j - 1];	//不选
			if(i >= v[j])f[i][j] = max(f[i][j-1],f[i-v[j]][j-1]+w[j]);	//选
		}
	}
	cout << f[m][n];
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);

	solve();
}

结果: Accepted
运行时间: 78 ms
运行空间: 4188 KB

优化

点击查看代码
void solve(){
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)cin >> v[i] >> w[i];
	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]);
		}
	}
	cout << f[m];
}

结果: Accepted
运行时间: 40 ms
运行空间: 216 KB

posted @   Keith-  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示