01背包问题

  • -- coding : GBK --
  • @Author : huangshengjiang
  • @Email : 1005542693@qq.com
  • @Date : 2017-04-12 09:24
  • @Last Modified Date : 2017-04-20 23:48
  • @FileName : 01背包问题.cpp

01背包问题
基本概念 : 用于某一维度约束的情况下,求另一维度的最大值或者最小值.
应用场景 : 如背包问题,固定里程花费最少等等.
具体需求 : 有n个物品和1个体积为C的背包,对于第i个物品,其体积为si,其价值为vi.如何选择使放入背包中的物品价值最大?
输入 : N C (N个物品,容量C的背包)
si vi
.. ..
(N对,si表示第i物体的体积,vi表示第i物体的价值)
输出 : 求出最大值MAX和选择的具体物品列表
分析 : 对于物品而言,只有放入背包(1)和未放入(0)两种状态.不考虑背包的体积,只关注物品的组合形式有2^n种,体积累加<=C,价格累加max.
时间复杂度达到O(n2^n).
子问题是f[i][j]表示将i个物品中选取若干件放入体积j的最大价值.
则有 f[i][j] = max{f[i-1]j,f[i-1][j-si]+vi(选取i物品)}.
其中f[0][j] = 0 j = 0,s1,s2,s3,..sn,s1+s2,s1+s3,...C ; f[i][0] = 0 i = 0..N ;
时间复杂度 : O(n+1
n/2)=O(n^2)
空间复杂度 : 一般用二维数组表示矩阵,可是实际中运用到的是矩阵的一半空间.可以用节点方式表示,是否节省空间待议?
引申问题 : 1.01背包问题隐形要求是物品最多选择1次,要是可选多次呢?
2.j物品有两个维度(sj,vj),sj累加<=C的情况下,求vj累加的最大值.如果有三个维度(x,y,z),x累加<=CX,Y累加<=CY,z累加的最大值呢?4个维度呢?
3.那最小值呢?
4.如果三个维度(x,y,z),在x累加<C的情况下,求y+z累加最大,或者y*z累加最大?

#include <iostream>
#include <vector>
using namespace std;
#define  N 100
//函数
struct good
{
	int value ;
	int cap  ;
};
good GOODS[N];

int  buf[N][N] = {0};

int  knapsack(int n,int c)
{
	int i = 0 ;
	int j = 0 ;
	n++ ;
	c++ ; 
	for ( ; i < n ; i++)
	{
		buf[i][0] = 0 ; 
	}
	for ( ; j < c ; j++)
	{
		buf[0][j] = 0;
	}
	for ( i = 1 ; i < n ; i++ )
	{
		for (j = 1 ; j < c ; j++)
		{
			buf[i][j] = buf[i - 1][j];
			if (j >= GOODS[i].cap)
			{
				buf[i][j] = buf[i][j] >= buf[ i - 1 ] [j - GOODS[i].cap] + GOODS[i].value ? buf[i][j] : buf[i - 1][j - GOODS[i].cap] + GOODS[i].value;
			}
		}
	}
	return buf[n-1][c-1];
}

//测试
int main(int argc, char const *argv[])
{
	freopen("C:\\Users\\hsj\\Desktop\\test.txt", "r", stdin);
	int n = 0, c = 0 ,vtmp = 0 , ptmp = 0;
	scanf("%d", &n);
	scanf("%d", &c);
	for (int i = 0 ; i < n ; i++ )
	{
		scanf("%d", &GOODS[i+1].cap);
		scanf("%d", &GOODS[i+1].value);
		//GOODS[i].
	}

	int result = knapsack( n , c );

	printf("最大总价值是%d", result);

	system("pause");
	return 0;
}

posted @ 2017-04-20 23:51  jiangge3  阅读(172)  评论(0编辑  收藏  举报