0-1背包问题 (vivo提前批笔试第二题)

在这里插入图片描述
在这里插入图片描述
现有n件物品,每一件的重量是w[i],价值是v[i]。用一个容量为c的背包来装这些东西, 问如何选择物品才能使装的物品价值最大?(每件物品只能放一次)
输入:
第一行:最大载重量c
第二行:每个集装箱的重量w[i],w[i]小于等于c,用逗号“,”分隔
第三行:每个集装箱对应货物的价值v[i],用逗号“,”分隔
输出:一个整数 表示货运总价值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;
typedef struct goods {
    int weight;
    int value;
}goods;
const int Capacity = 11;//总容量
const int N = 5;      //物品件数
goods comodity[N + 1] = { {0,0},{1,1},{2,6 }, {5, 18}, {6, 22}, {7, 28} };
int selected[N + 1][Capacity + 1];

int Max(int a,int b) {
    return a > b ? a : b;
}

int GetMaxValue() {
    for (int w = 0; w <= Capacity; w++)
        selected[0][w] = 0;   //表示容量为w的背包为空时,其价值为0
    for (int i = 1; i <= N; i++)
        selected[i][0] = 0;   //表示容量为0的背包,其价值为0
    for(int i=1;i<=N;i++)
        for (int w = 1; w <= Capacity; w++) {
            if (comodity[i].weight > w)
                selected[i][w] = selected[i - 1][w];//不装第i件物品
            else
                selected[i][w] = Max(selected[i - 1][w], comodity[i].value + selected[i - 1][w - comodity[i].weight]);//在装与不装之间选个大的
        }
    return selected[N][Capacity];
}
int main()
{
    cout << "Max Value is " << GetMaxValue() << endl;
    int remainspace = Capacity;
    for (int i = N; i > 0; i--) {
        //从最优解出发,将所有满足选中状态的物品编号输出即可得到最优解的组成
        if (selected[i][remainspace] == comodity[i].value + selected[i - 1][remainspace - comodity[i].weight]) {
            cout << "item " << i << " is selected" << endl;
            remainspace -= comodity[i].weight;//空位置大小更新
        }
    }
    return 0;
}

https://www.bilibili.com/video/BV1K4411X766?from=search&seid=5111710240287021888
这个讲的太好了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

https://www.cnblogs.com/TWS-YIFEI/p/9761200.html

在这里插入图片描述
此时看代码就清楚多了
在这里插入图片描述
以上代码在vs上会报错不知道为啥(注释掉的没错)

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
	int c=5;//容量
	int w[505];
	int v[505];
	int dp[505];
	string str1 = "1,2,3", str2 = "6,10,12";
	//cin >> c >> str1 >> str2;
	int n = str1.size();
	int cnt= 0;
	for (int i = 0; i < n; ++i){
		int num = 0;
		while (str1[i] != ','&& i < n){
			num = 10 * num + str1[i++] - '0';
			
		}w[cnt++] = num;
	}//w数组填入
	n = str2.size();
	cnt = 0;
	for (int i = 0; i < n; ++i){
		int num = 0;

		while (str2[i] != ','&& i < n){
			num = 10 * num + str2[i++] - '0';
			 
		}v[cnt++] = num;
	}//v数组填入
	for (int i = 0; i < cnt; ++i){
		int weight = w[i];
		for (int j = c; j >= weight; --j){
			dp[j] = max(dp[j],dp[j-weight]+v[i]);
		}

	}
	cout << dp[c] << endl;
	system("pause");
	return 0;
}

//int main() {
//	vector<int> weight = { 1, 2, 3 };
//	vector<int> value = { 6, 10, 12 };
//	int c = 5;
//
//	// 初始化
//	vector<int> dp(c + 1, 0);
//	for (int i = 0; i < weight.size(); i++) { // 遍历物品
//		for (int j = c; j >= weight[i]; j--) { // 遍历背包容量
//			dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
//		}
//	}
//	cout << dp[c] << endl;
//		system("pause");
//		return 0;
//}


还有另一种输入方法:在这里插入图片描述
在网页在线上可以ac

https://www.nowcoder.com/questionTerminal/708f0442863a46279cce582c4f508658?questionTypes=000100&page=1&onlyReference=false

#include<iostream>
#include<math.h>
using namespace std;
int main(){
    int n,c;
    cin>>c>>n;
    int w[n],v[n],dp[c+1];
    for(int i=0;i<n;i++)
        cin>>w[i]>>v[i];
    for(int j=0;j<=c;j++)
        if(w[0]<=j) dp[j]=v[0];
        else dp[j]=0;
    for(int i=1;i<n;i++)
        for(int j=c;j>=w[i];j--){
            dp[j]=max(dp[j], v[i]+dp[j-w[i]]);
        }
    cout<<dp[c]<<endl;
    return 0;
}

感觉一维数组的算法还是有点难懂 在这里插入图片描述
这一步在vivo里就没有 但是在牛客上就得有
还是好好记一下二维数组的写法吧
不过下面这个写的也不错

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int w, n;//容量 件数
    cin>>w>>n;
	vector <int> weight(1), value(1);//这个1必须有
	for (int i = 0; i < n; i++)
		{
			int wei, val;
			cin >> wei >> val;
			weight.push_back(wei);
			value.push_back(val);
		}
		vector<int> result(w + 1);//这个w+1必须有
		for (int i = 1; i <= n; i++)
		{
			for (int j = w; j >=weight[i]; j--)
			{
				result[j] = max(result[j], result[j - weight[i]] + value[i]);
			}
		}
		cout << result[w] << endl;
	return 0;
}

几个for的条件很重要 麻了
这样改过以后舒服多了 还是用的vector 数组不知道为什么不行

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int w, n;//容量 件数
    //for (int i = 0; i<n; i++)
	//cin >> w[i] >> v[i];
    cin>>w>>n;
	vector <int> weight, value;//这里去掉了(1)
	for (int i = 0; i < n; i++)
		{
			int wei, val;
			cin >> wei >> val;
			weight.push_back(wei);
			value.push_back(val);
		}
		vector<int> result(w+1);//这个还是必须要有 因为后面有weight[i]
								//但是如果变成一个具体的数字就又会报错 不懂
		for (int i = 0; i < n; i++)//因为weight和value数组的第一个元素不是0了
								   // 所以这里就从0开始 而不是1
		{
			for (int j = w; j >=weight[i]; j--)
			{

				result[j] = max(result[j], result[j - weight[i]] + value[i]);

			}
		}
		cout << result[w] << endl;
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值