01背包问题四种不同算法的实现Word文档下载推荐.docx
- 文档编号:14843007
- 上传时间:2022-10-25
- 格式:DOCX
- 页数:40
- 大小:173.33KB
01背包问题四种不同算法的实现Word文档下载推荐.docx
《01背包问题四种不同算法的实现Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《01背包问题四种不同算法的实现Word文档下载推荐.docx(40页珍藏版)》请在冰豆网上搜索。
j++)
if(c[j]<
c[j+1])
{t1=a[j];
a[j]=a[j+1];
a[j+1]=t1;
t2=b[j];
b[j]=b[j+1];
b[j+1]=t2;
t3=c[j];
c[j]=c[j+1];
c[j+1]=t3;
}
voidknapsack(intn,floatlimitw,floatv[max],floatw[max],intx[max])
{floatc1;
//c1为背包剩余可装载重量
inti;
sort(n,v,w);
//物品按价值密度排序
c1=limitw;
for(i=0;
i<
i++)
if(w[i]>
c1)break;
x[i]=1;
//x[i]为1时,物品i在解中
c1=c1-w[i];
voidmain()
{intn,i,x[max];
floatv[max],w[max],totalv=0,totalw=0,limitw;
cout<
<
"
请输入n和limitw:
;
cin>
>
n>
limitw;
for(i=1;
=n;
x[i]=0;
//物品选择情况表初始化为0
请依次输入物品的价值:
endl;
v[i];
请依次输入物品的重量:
w[i];
knapsack(n,limitw,v,w,x);
theselectionis:
x[i];
if(x[i]==1){
totalw=totalw+w[i];
totalv=totalv+v[i];
背包的总重量为:
totalw<
//背包所装载总重量
背包的总价值为:
totalv<
//背包的总价值
4、贪心算法运行结果如下图所示:
方案二:
动态规划算法
1、动态规划的基本原理与分析
动态规划算法的基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
但是经分解得到的子问题往往不是互相独立的。
不同子问题的数目常常只有多项式量级。
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。
它把已知问题分为很多子问题,按顺序求解子问题,在每一种情况下,列出各种情况的局部解,按条件从中选取那些最有可能产生最佳的结果舍弃其余。
前一子问题为后面子问题提供信息,而减少计算量,最后一个子问题的解即为问题解。
采用此方法求解0-1背包问题的主要步骤如下:
①分析最优解的结构:
最有子结构性质;
②建立递归方程;
③计算最优值;
④构造最优解[4]。
2、0-1背包问题的实现
①最优子结构性质
0-1背包问题具有最优子结构性质。
设(y1,y2…yn)是所给0-1背包问题的一个最优解,则(y2,y3…yn)是下面相应子问题的一个最优解:
因若不然,设(z2,z3…zn)是上述问题的一个最优解,而(y2,y3…yn)不是它的最优解,由此可见,且c。
因此
c
这说明(y1,z2…zn)是所给0-1背包问题的一个更优解,从而(y1,y2…yn)不是所给0-1背包问题的最优解。
此为矛盾[1]。
②递归关系
设所给0-1背包问题的子问题
的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,……,n时0-1背包问题的最优值。
由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下:
iostream>
iomanip>
usingnamespacestd;
constintMAX=1000;
intw[MAX],v[MAX],best[MAX];
intV[MAX][MAX];
//最大价值矩阵
intW,n;
//W为背包的最大载重量,n为物品的数量
//求最大值函数
intmax(intx,inty)
returnx>
=y?
x:
y;
//求最小值函数
intmin(intx,inty)
returnx>
=y?
y:
x;
voidKnaspack()
intMax=min(w[n]-1,W);
for(intj=1;
j<
=Max;
j++)
V[n][j]=0;
for(j=w[n];
=W;
V[n][j]=v[n];
for(inti=n-1;
i>
1;
i--)
{
Max=min(w[i]-1,W);
for(j=1;
V[i][j]=V[i+1][j];
for(j=w[i];
=W;
V[i][j]=max(V[i+1][j],V[i+1][j-w[i]]+v[i]);
}
V[1][W]=V[2][W];
//先假设第一个物品不放入
if(W>
w[1])
V[1][W]=max(V[1][W],V[2][W-w[1]]+v[1]);
//生成向量数组,决定某一个物品是否应该放入背包
voidTraceback()
for(inti=1;
i<
n;
i++)//比较矩阵两邻两行(除最后一行),背包容量为W的最优值.
if(V[i][W]==V[i+1][W])//如果当前行的最优值与下一行的最优值相等,则表明该物品不能放入。
best[i]=0;
else//否则可以放入
{
best[i]=1;
W-=w[i];
}
}
best[n]=(V[n][W])?
1:
0;
{
cout<
输入商品数量n和背包容量W:
cin>
n>
W;
输入每件商品的重量w:
cin>
memset(V,0,sizeof(V));
输入每件商品的价值v:
for(i=1;
Knaspack();
//构造矩阵
Traceback();
//求出解的向量数组
inttotalW=0;
inttotalV=0;
//显示可以放入的物品
所选择的商品如下:
序号i:
重量w:
价格v:
for(i=1;
=n;
i++)
if(best[i]==1)
totalW+=w[i];
totalV+=v[i];
cout<
setiosflags(ios:
:
left)<
setw(5)<
"
w[i]<
v[i]<
放入的物品重量总和是:
totalW<
价值最优解是:
V[1][W]<
totalV<
4、计算复杂性分析
利用动态规划求解0-1背包问题的复杂度为0(min{nc,2n}。
动态规划主要是求解最优决策序列,当最优决策序列中包含最优决策子序列时,可建立动态规划递归方程,它可以帮助高效地解决问题[8]。
5、动态规划运行结果如下图所示:
方案三:
回溯法
1、回溯法的基本原理与分析
回溯是一种系统地搜索问题解答的方法。
为了实现回溯,首先需要为问题定义一个解空间,这个解空间必须至少包含问题的一个解(可能是最优的)。
回溯法需要为问题定义一个解空间,这个解空间必须至少包含问题的一个解(可能是最优的)。
使用递归回溯法解决背包问题的优点在于它算法思想简单,而且它能完全遍历搜索空间,肯定能找到问题的最优解奉但是由于此问题解的总组合数有个,因此随着物件数n的增大,其解的空间将以n级增长,当n大到一定程度上,用此算法解决背包问题将是不现实的。
下一步是组织解空间以便它能被容易地搜索。
典型的组织方法是图或树。
一旦定义了解空间的组织方法,这个空间即可按照深度优先的方法从开始结点进行搜索,利用限界函数避免移动到不可能产生解的子空间。
回溯法是一种系统地搜索问题解答的方法。
一旦定义了解空间的组织方要选择一个对象的子集,将它们装人背包,以便获得的收益最大,则解空间应组织成子集树的形状。
首先形成一个递归算法,去找到可获得的最大收益。
然后,对该算法加以改进,形成代码。
改进后的代码可找到获得最大收益时包含在背包中的对象的集合。
左子树表示一个可行的结点,无论何时都要移动到它,当右子树可能含有比当前最优解还优的解时,移动到它。
一种决定是否要移动到右子树的简单方法是r为还未遍历的对象的收益之和,将r加到cp(当前节点所获收益)之上,若(r+cp)bestp(目前最优解的收益),则不需搜索右子树。
一种更有效的方法是按收益密度vi/wi对剩余对象排序,将对象按密度递减的顺序去填充背包的剩余容量,当遇到第一个不能全部放人背包的对象时,就使用它的一部分。
classKnap
friendintKnapsack(intp[],intw[],intc,intn);
public:
voidprint()
for(intm=1;
m<
m++)
bestx[m]<
};
private:
intBound(inti);
voidBacktrack(inti);
intc;
//背包容量
int
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 01 背包 问题 不同 算法 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)