0/1背包问题
题目描述:
有n个重量分别为w1,w2,…,wn的物品(物品编号为1~n),它们的价值分别为v1,v2,…,vn,给定一个容量为W的背包。设计从这些物品中选取一部分物品放入该背包的方案,每个物品要么选中要么选不中,要求选中的物品不仅能够放到背包中,而且具有最大价值,并对下表所示4个物品求出W=6时的所有解和最佳解。

分析思路:回溯法
设n件物品重量分别为w1,w2,…,wn的物品,用数组w[1 … n]存放,物品的价值分别为v1,v2,…,vn,用数组v[n]存放;限制重量用W表示。用x[1 … n]数组存放最优解,其中每个元素取1或0,x[i]=1表示第i个物品放入背包中,x[i]=0表示第i个物品不放入背包中。
最优解问题,显然其解空间是子集树(每个物品要么装入,要么不装入),每个结点表示背包的一种选择状态,记录当前放入背包的物品总重量和总价值,每个分枝结点下面有两条边表示对某物品是否放入背包的两种可能选择。
第i层上的某个分枝结点的对应状态为dfs(1,tw,tv,op),其中
tw:表示装入背包中的的物品总重量
tv:表示背包中物品总价值
op:记录一个解向量
时间复杂度:O(2^n)
该状态两种扩展如下:
(1)选择第i个物品放入背包中:op[i]=1,tw=tw+w[i],tv=tv+v[i],转向下一个状态dfs=(i+1,tw,tv,op).该对策对应左分枝
(2)不选择第i个物品放入背包:op[i]=0,tw=tw不变,tv不变,转向下一个状态dfs=(i+1,tw,tv,op).该对策对应右分枝
叶子结点表示已经对n个物品做了决策,对应一个解。对所有叶子结点进行比较求出满足tw=W的最大tv(用maxw表示),将对应的最优解op存放到x中
对于表4.2所示的4个物品,在限制背包总重量W=6时描述问题求解过程的解空间树如图所示,每个结点中的两个数值为(tw,tv)
对于层次为1的根结点为(0,0),考虑物品1
(1)选择物品1:op[1]=1,tw=0+5,tv=0+4,产生新结点(5,4)作为根的左孩子
(2)不选择物品1:op[1]=0,tw=0,tv=0,产生新结点(0,0)作为根的右孩子

对于层次2的(5,4)结点,考虑物品2
(1)选择物品2:op[2]=1,tw=5+3=8,tv=4+4=8,产生新结点(8,8)作为其左孩子。
(2)不选择物品2:op[2]=0,tw=5,tv=4,产生新结点(5,4)作为其右孩子。
这样可构造出整棵子集树31个结点
递归代码:
#include<stdio.h>
#define MAXN 20 //最多20个物品
int n=4; //4种物品
int W=6; //最大重量6
int w[]={
0,5,3,2,1}; //存放4个物品重量,下标为0元素不用
int v[]={
0,4,4,3,1}; //存放4个物品价值,下标为0元素不用
int x[MAXN]; //最终解
int maxv; //最优解
void dfs(
9263



被折叠的 条评论
为什么被折叠?



