##################################################################################################
背包问题(Knapsack problem)是一种组合优化的NP完全问题。
问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,
在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
问题的名称来源于如何选择最合适的物品放置于给定背包中。
我们有n种物品,物品j的重量为wj,价格为pj。我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。
如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题。可以用公式表示为:
框中上面内容来自:维基百科->背包问题
#################################################################################################
#######################################################################
##############
框中内容来自《0-1背包问题递归实现与非递归实现--动态规划》
程序为:
/**************************************************************
*0 1 背包问题
* 参考URI:http://www.cnblogs.com/justinzhang/archive/2012/04/10/2441199.html
*
*给定一个背包,容量为c,有n个物品,
*重量为n维行向量w,
*价值为n维行向量v.
*n维向量y=[0,1,0….yn]代表物品的选法,其中的没有元素yi,要么是0、要么是1,
* 为1代表选取第i个物品,为0表示不选取第i个物品。
*目标函数是:Max(Sum(vi*yi)), 约束条件是sum(wi*yi) <=C, 其中 1=< i <=n.
*
*
*背包问题具有最优子结构,
*令f(n,c)代表,有n个待选物品,背包容量为C时的最优解,
*此时物品选择向量为y=[y1,y2,…yn], 那么当y[n]=1时,y'=[y1, y2, …yn-1],必然为f(n-1, c-wn)的物品选择向量,
*当y[n]=0时,必然为f(n-1,c)的最优物品选择向量。
*所以背包问题可以由动态规划来求解。
*根据上面的分析,我们可以得到如下的递归式:
*当w[n]>C时, f(n,c)=f(n-1,c);
*当w[n]<=C时,f(n,c) = max(f(n-1,c), vn+f(n-1, c-wn) );
*初始条件为:f(i, 0) = 0; f(0,i) = 0; f(0,0) = 0;
*
*
*
*
**************************************************************/
#include <stdio.h>
int w[] = {1, 3, 4, 5}; //物品重量数组,从下标0开始
int v[] = {2, 30, 44, 20}; //物品价值数组,从下标0开始
int c = 5; //背包容量
int y[4] = {-1,-1,-1,-1}; //为0表示不选取物品,为1表示选取物品
/*******************************************************************
*description: 获取背包所装物品最大价值
*function: int f(int n, int c)
*input: n :物品个数
*input: c :背包容量
*
*return: 背包所装物品最大价值
*
********************************************************************/
int f(int n, int c)
{
if(n==0 || c==0)
{
return 0;
}
int i = 0;
//从当前所剩物品的左后一个物品开始向前,逐个判断是否要添加到背包中
for(i=n-1; i>=0; i--)
{
//如果当前所剩物品的最后一个物品开始向前,逐个判断是否要添加到背包中
//在这种情况的最优解为f(n-1, c)
if(w[i] > c)
{
y[i] = 0;
return f(n-1,c);
}
else
{
//如果当前待判断的物品重量w[i]<=c,那么就选取f(n-1,C)和vi+f(n-1,C-wi)中的最大值
int temp1 = f(n-1, c); //不选择物品i的情况下的最有将诶
int temp2 = v[i] + f(n-1, c-w[i]); //选择物品i的情况下的最优解
//返回选择物品i和不选择物品i中最优解大的一个
if(temp1>temp2)
{
y[i] = 0; //不取物品i
return temp1;
}
else
{
y[i] = 1; //取物品i
return temp2;
}
}
}
}
int main(void)
{
//物品个数为4,背包容量为5,求最优值
// int w[] = {1, 3, 4, 5}; //物品重量数组,从下标0开始
// int v[] = {2, 30, 44, 20}; //物品价值数组,从下标0开始
// int c = 5; //背包容量
int maxValue = f(4, 5);
int i = 0;
for(i=0; i<4; i++)
{
printf("%d ",y[i]);
}
printf("\n%d\n", maxValue);
return 0;
}
#####################################################################################
--------------------------------------------------------------------------------------------------
上述程序可以求出在满足sum(w[i]) 其中i=0……n-1,求出所装物品的最大值sun(v[i]*y[i])及所装物品对应的下标,装入为1,否则为0; 但是我想求出最大值为sun(v[i]*y[i]*w[i]) i=0……n-1,可以求出结果但是输出对应的物品的下标却不对。