动态规划之0-1背包问题

问题描述:一组物品编号1,2,...,N,每个物品重量v[i],价值w[i],挑出若干件物品放入一个能容纳物品重量V背包中,这些物品的总重不超过V,且价值要尽量大。

解题思路:设把1,2,...,i物品挑出若干放入能容纳v重量的背包中,所能产生的最大价值为f[i][v]。如果第i件物品没有放入背包,那么f[i][v]=f[i-1][v];如果第i件物品放入了背包中那么f[i][v]=f[i-1][v-w[i]]+w[i]。为使价值最大化,应取二者较大的:

f[i][v]=max{f[i-1][v],f[i-1][v-v[i]]+w[i]}

上式就是0-1背包问题的状态转移方程,根据该方程很容易写出代码:

#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

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

void print_elems(vector<vector<int>> &v)
{
	vector<vector<int>>::iterator it_row;
	vector<int>::iterator it_column;
	for (it_row = v.begin(); it_row != v.end(); ++it_row)
	{
		for (it_column = (*it_row).begin(); it_column != (*it_row).end(); ++it_column)
		{
			cout << *it_column << ' ';
		}
		cout << endl;
	}
}

int main(void)
{
	int a[] = { 0, 10, 40, 30, 50 };
	int b[] = { 0, 5, 4, 6, 3 };
	int max_weight = 10;
	vector<int> values(a, a + 5);
	vector<int> weight(b, b + 5);
	int row = values.size();
	int column = max_weight + 1;
	vector<vector<int>> grid(row, vector<int>(column, 0));
	int i, j;
	for (i = 1; i < row; ++i)
	{
		for (j = 1; j < column; ++j)
		{
			if (j >= weight[i])
			{
				grid[i][j] = max(grid[i - 1][j], values[i] + grid[i - 1][j - weight[i]]);
			}
			else
				grid[i][j] = grid[i - 1][j];
		}
	}

	print_elems(grid);

	return 0;
}
运行结果:

上述代码的时间复杂度和空间复杂度都是O(V*N)。实际上空间复杂度还可以降到O(V),也就是用一个一维数组来保存数据,需要用到的小技巧就是v要从大到小,也就是说数组f存放前i-1件物品放入重量为1,2,...,V背包中能获得的最大价值。在求前i件物品放入重量为1,2,...,V背包中能获得的最大价值应先求f[i][V],他要用到的f[i-1][V]和f[i-1][V-w[i]]都在f数组中,求出来后,原地放入数组f中,然后更新V-1,...,1,这样就求出了前i件物品放入重量为1,2,...,V背包中能获得的最大价值,且仍保存在f中。

代码:

#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

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

void print_elems(vector<int>& v)
{
	for (vector<int>::const_iterator it = v.begin(); it != v.end();++it)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

int main(void)
{
	int a[] = { 0, 10, 40, 30, 50 };
	int b[] = { 0, 5, 4, 6, 3 };
	int max_weight = 10;
	vector<int> values(a, a + 5);
	vector<int> weight(b, b + 5);
	int row = values.size();
	int column = max_weight + 1;
	vector<int> f(column, 0);
	int i, j;
	for (i = 1; i < row; ++i)
	{
		for (j = column-1; j > 0; --j)
		{
			if (j >= weight[i])
			{
				f[j] = max(f[j], values[i] + f[j - weight[i]]);
			}
		}
		print_elems(f);
	}

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值