背包问题

Posted oscar67

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了背包问题相关的知识,希望对你有一定的参考价值。


  现有n件物品和一个容量为c的背包。第i件物品的重量是重量为w[i],价值是v[i]。已知对于一件物品必须选择取(用1表示)或者不取(用0表示),且每件物品只能被取一次(这就是“0-1”的含义)。求放置哪些物品进背包,可使这些物品的重量总和不超过背包容量,且价值总和最大。

 01背包问题:

  c[i][j] = Max(c[i - 1][j], c[i - 1][j - weight[i]] + value[i]);

  递归公式表示 当前的最优解 = Max(不放入当前的的物品,即c[i - 1][j]    ,      放入当前物品,则要预留出这个物品的 位置 即   c[i - 1][j - weight[i]] + value[i]  )

  然后递归得到所有的解。

  每个物品只考虑放不放入一个,完全背包问题就考虑1~max个,多重就是考虑指定数量的物品,具体见代码。

  

// Study.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <string>
#include <algorithm>
#include <sstream>
#include <set>
#include <stack>
#define INT_MAX 2147483647 // maximum (signed) int value
#define INT_MIN (-2147483647 - 1) // minimum (signed) int value
;


using namespace std;

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

void baggage(int m, int n, vector<int> &weight, vector<int> &value)
{
	vector<vector<int>> c(n + 1, vector<int>(m + 1, 0));

	vector<int> t(m + 1, 0);
	//01背包问题
	for (int i = 1; i <= n; i++)
	{
		for (int j = m; j >= 1; j--)
		{
			if (weight[i] <= j)
			{
				c[i][j] = Max(c[i - 1][j], c[i - 1][j - weight[i]] + value[i]);
			}
			else
				c[i][j] = c[i - 1][j];
		}
	}

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cout << c[i][j] << " ";
		}
		cout << endl;
	}
	//*******************************完全背包问题*************
	cout << endl << "完全背包 " << endl;
	for (int i = 1; i <= n; i++)
	{
		for (int j = m; j >= 1; j--)
		{
			for (int k = 1; k <= j / weight[i]; k++)
				c[i][j] = Max(c[i - 1][j], c[i - 1][j - k * weight[i]] + k * value[i]);
		}
	}

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cout << c[i][j] << " ";
		}
		cout << endl;
	}

	//*********多重背包问题***********
	vector<int> num = { 0,1,1,1 };
	cout << endl << "多重背包 " << endl;
	for (int i = 1; i <= n; i++)
	{
		for (int j = m; j >= 1; j--)
		{
			for (int k = 1; k <= j / weight[i] && k <= num[i]; k++)
				c[i][j] = Max(c[i - 1][j], c[i - 1][j - k * weight[i]] + k * value[i]);
		}
	}

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cout << c[i][j] << " ";
		}
		cout << endl;
	}

	/*
	//用一位数组节省空间

	for (int i = 1; i <= n; i++)
	{
	for (int j = m; j >= 1; j--)
	{
	if (weight[i] <= j)
	{
	t[j] = Max(t[j], t[j - weight[i]] + value[i]);
	}
	else
	t[j] = t[j];
	}
	}


	for (int j = 1; j <= m; j++)
	{
	cout << t[j] << " ";
	}
	cout << endl;
	*/

}

int main()
{
	int M, N;
	//cin >> M >> N;

	//vector<int> weight(N+1, 0);
	//vector<int> value(N+1, 0);
	//for (int i = 1; i <= N; i++)
	//{
	//	cin >> weight[i] >> value[i];
	//}

	M = 10, N = 3;
	vector<int> weight = { 0,3,4,5 };
	vector<int> value = { 0,4,5,6 };

	baggage(M, N, weight, value);
	system("pause");
	return 0;
}

  


以上是关于背包问题的主要内容,如果未能解决你的问题,请参考以下文章

使用喷气背包导航将自定义过渡动画添加到底部导航设置

在片段的后按防止使用导航图调用前一个片段的 onViewCreated

Android Jetpack 导航禁用滚动位置

0-1背包问题的回溯法代码

c语言背包问题,求高手解答

动态规划_01背包_完全背包_多重背包_分组背包