01背包问题

原创 2016年08月29日 19:45:37

01背包问题是经典的动态规划问题,问题描述如下:


我们用f[i][j]表示将前i个物品放入容量为j的背包里所能获得的最大价值,则状态转移方程如下:


具体程序如下:

#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;
int maxValue(vector<int>weight,vector<int>value,int bagCapacity)
{
	int m=weight.size();
	int n=bagCapacity;
	vector<vector<int>>dp(m+1,vector<int>(n+1,0));
	vector<int> rollDp(n+1,0);
	for(int i=0;i<m;++i)
	{
		for(int j=n-1;j>=0;--j)
		{
			if(weight[i]<=j+1)
			{
				dp[i+1][j+1]=max(dp[i][j+1],dp[i][j+1-weight[i]]+value[i]);  //当内循环从右到左时,可以用滚动数组来优化空间复杂度。
				rollDp[j+1]=max(rollDp[j+1],rollDp[j+1-weight[i]]+value[i]); //用于滚动数组降低空间复杂度
			}
			else
			{
				dp[i+1][j+1]=dp[i][j+1];
			}

		}
	}
	cout<<"滚动数组所得结果为: "<<rollDp[n]<<endl;  //滚动一维数组输出结果和二维数组一致
	return dp[m][n];
}
int main()
{ 
	int numCnt=0;   //物品数目
	int bagCapacity=0;  //背包容量
	while(cin>>numCnt>>bagCapacity)
	{
		vector<int>weight(numCnt,0);
		vector<int>value(numCnt,0);
		for(int i=0;i<numCnt;++i)
		{
			cin>>value[i];
		}
		for(int i=0;i<numCnt;++i)
		{
			cin>>weight[i];	
		}
		cout<<"最大价值为: "<<maxValue(weight,value,bagCapacity);
	}
}
程序运行结果如下:


上述输入第一行第一个数代表物品个数,第二个数代表背包最大容量;第二行每个数分别代表对应的物品的价值,第三行每个数分别代表对应物品的重量。

从程序中我们可以看到如果利用二维数组dp来编写程序,就是完全按照我们之前写的状态转移方程来写,这个很好理解,但是空间复杂度为O(N*W)。我们注意到状态转移方程中dp[i][j]只与dp[i-1][]有关(第二维空着不是笔误哦,我是想表达的是外层的第i个循环的值,只与外层的第i-1个循环的值决定,这样一来,内层循环不管顺序还是逆序都可以,自己思考一下为什么?),而当内层循环逆序的时候,我们通常可以用一维数组来代替二维数组,原因如下:这种情况下我们可以用dp[j]取代dp[i][j]是因为计算dp[i][j]前,我们已经计算了dp[i-1][j],所以如果我们之前是用的一维数组dp[j]的话,那计算dp[i][j]前一瞬间,dp[j]代表的是dp[i-1][j],dp[i][j]计算完后,dp[j]表示的就是dp[i][j],程序中我将这两种方法写到了一起,方便领悟其中的差别。现在我们思考一个问题,为什么用一维数组的时候,内层循环必须是逆序,不能顺序?原因是

dp[i+1][j+1]=max(dp[i][j+1],dp[i][j+1-weight[i]]+value[i]),注意到式中有dp[i][j+1-weight[i]],如果假设j+1-weight[i]=3,那当我们求dp[i+1][j+1],而j=6时,此时用二维数组肯定不会有问题,但是用一维数组且内循环顺序增长时,此时dp[j+1]即dp[7]可能与dp[3]有关,但此时的dp[3]已经是dp[i+1][3]了,而不再是dp[i][3],违背了我们的状态转移方程。




                    
版权声明:本文为博主原创文章,未经博主允许不得转载。

动态规划_01背包问题_Java实现

什么是动态规划?动态规划就是将一个大问题不断向下拆分成小问题,直到拆分出的小问题可以求出其解,然后将小问题的解不断的向上合并,最终得到大问题的解决方案。...
  • ljmingcom304
  • ljmingcom304
  • 2015年12月16日 15:11
  • 5276

01背包问题 及c++ 代码实现

今天在看july的博客之时,看到其中一道题目的原理为01背包问题,就自己温习了下,写下今天的学习体会。 本文理论分析参考博客:http://www.cnblogs.com/qinyg/archive...
  • zhaowenchaofang
  • zhaowenchaofang
  • 2013年06月14日 01:12
  • 4101

总结——01背包问题 (动态规划算法)

0-1 背包问题:给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi 。 问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?...
  • xp731574722
  • xp731574722
  • 2017年04月25日 20:57
  • 8873

01背包问题

  • 2014年09月17日 20:01
  • 527B
  • 下载

01背包問題,用跳越點解

  • 2013年11月16日 19:04
  • 6KB
  • 下载

01背包问题

  • 2016年03月24日 10:04
  • 40KB
  • 下载

遗传算法解决01背包问题

  • 2015年03月06日 21:04
  • 381KB
  • 下载

c c++ 01背包问题动态规划解决

  • 2013年11月05日 16:45
  • 28KB
  • 下载

C#实现-动态规划-01背包问题(Knapsack)

  • 2017年11月19日 14:43
  • 53KB
  • 下载

01背包问题

  • 2017年12月19日 21:52
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:01背包问题
举报原因:
原因补充:

(最多只允许输入30个字)