蛮力法、动归、贪心、分支限界法解01背包问题剖析
贪心算法-01背包问题
贪⼼算法-01背包问题
1、问题描述:
给定n种物品和⼀背包。物品i的重量是wi,其价值为vi,背包的容量为C。问:应如何选择装⼊背包的物品,使得装⼊背包中物品的总价值最⼤?
形式化描述:给定c >0, wi >0, vi >0 , 1≤i≤n.要求找⼀n元向量(x1,x2,…,xn,), xi∈{0,1}, ∋ ∑ wi xi≤c,且∑ vi xi达最⼤.即⼀个特殊的整数规划问题。
2、最优性原理:
设(y1,y2,…,yn)是 (3.4.1)的⼀个最优解.则(y2,…,yn)是下⾯相应⼦问题的⼀个最优解:
证明:使⽤反证法。若不然,设(z2,z3,…,zn)是上述⼦问题的⼀个最优解,⽽(y2,y3,…,yn)不是它的最优解。显然有
∑vizi > ∑viyi (i=2,…,n)
且 w1y1+ ∑wizi<= c
因此 v1y1+ ∑vizi (i=2,…,n) > ∑ viyi, (i=1,…,n)
说明(y1,z2, z3,…,zn)是(3.4.1)0-1背包问题的⼀个更优解,导出(y1,y2,…,yn)不是背包问题的最优解,⽭盾。
3、递推关系:
设所给0-1背包问题的⼦问题
的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优⼦结构性质,可以建⽴计算m(i,j)的递归式:
注:(3.4.3)式此时背包容量为j,可选择物品为i。此时在对xi作出决策之后,问题处于两种状态之⼀:
(1)背包剩余容量是j,没产⽣任何效益;
背包问题-贪心法和动态规划法求解
实验四“0-1”背包问题
一、实验目的与要求
熟悉C/C++语言的集成开发环境;
通过本实验加深对贪心算法、动态规划算法的理解。
二、实验内容:
掌握贪心算法、动态规划算法的概念和基本思想,分析并掌握“0-1”背包问题的求解方法,并分析其优缺点。
三、实验题
1.“0-1”背包问题的贪心算法
2.“0-1”背包问题的动态规划算法
说明:背包实例采用教材P132习题六的6-1中的描述。要求每种的算法都给出最大收益和最优解。
设有背包问题实例n=7,M=15,,(w0,w1,。。。w6)=(2,3,5,7,1,4,1),物品装入背包的收益为:(p0,p1,。。。,p6)=(10,5,15,7,6,18,3)。求这一实例的最优解和最大收益。
四、实验步骤
理解算法思想和问题要求;
编程实现题目要求;
上机输入和调试自己所编的程序;
验证分析实验结果;
整理出实验报告。
五、实验程序
// 贪心法求解
#include<iostream>
#include"iomanip"
using namespace std;
//按照单位物品收益排序,传入参数单位物品收益,物品收益和物品重量的数组,运用冒泡排序
void AvgBenefitsSort(float *arry_avgp,float *arry_p,float *arry_w );
//获取最优解方法,传入参数为物品收益数组,物品重量数组,最后装载物品最优解的数组和还可以装载物品的重量
float GetBestBenifit(float*arry_p,float*arry_w,float*arry_x,float u);
TSP问题的解决方案
《算法设计与分析》实验报告一
学号:姓名:
日期:20161230 得分:
一、实验内容:
TSP问题
二、所用算法的基本思想及复杂度分析:
1、蛮力法
1)基本思想
借助矩阵把问题转换为矩阵中点的求解。首先构造距离矩阵,任意节点到自身节点的距离为无穷大。在第一行找到最小项a[1][j],从而跳转到第j行,再找到最小值a[j][k],再到第k行进行查找。。。然后构造各行允许数组row[n]={1,1…1},各列允许数组colable[n]={0,1,1….1},其中1表示允许访问,即该节点未被访问;0表示不允许访问,即该节点已经被访问。如果改行或该列不允许访问,跳过该点访问下一节点。程序再发问最后一个节点前,所访问的行中至少有1个允许访问的节点,依次访问这些节点找到最小的即可;在访问最后一个节点后,再次访问,会返回k=0,即实现访问源节点,得出一条简单回路。
2)复杂度分析
基本语句是访问下一个行列中最小的点,主要操作是求平方,假设有n个点,则计算的次
页脚内容1
数为n^2-n。T(n)=n*(n-1)=O(n^2)。
2、动态规划法
1)基本思想
假设从顶点s出发,令d(i, V’)表示从顶点i出发经过V’(是一个点的集合)中各个顶点一次且仅一次,最后回到出发点s的最短路径长度。
推导:(分情况来讨论)
①当V’为空集,那么d(i, V’),表示从i不经过任何点就回到s了,如上图的城市3->城市0(0
为起点城市)。此时d(i, V’)=Cis(就是城市i 到城市s 的距离)、
②如果V’不为空,那么就是对子问题的最优求解。你必须在V’这个城市集合中,尝试每一个,
01背包各种算法代码实现总结(穷举,贪心,动态,递归,回溯,分支限界)
01背包各种算法代码实现总结(穷举,贪⼼,动态,递归,回
溯,分⽀限界)
2020-05-22
所有背包问题实现的例⼦都是下⾯这张图
01背包实现之——穷举法:
1.我的难点:
(1)在⽤穷举法实现代码的时候,我⾃⼰做的时候认为最难的就是怎么将那么多种情况表⽰出来,⼀开开始想⽤for循环进⾏多次嵌套,但是太⿇烦,⽽且还需要不断的进⾏各种标记。我现在的⽔平实在太菜,然后就在⼀篇中看到⼀个特别巧妙的枚举算法,如下所⽰:
int fun(int x[n])
{
int i;
for(i=0;i<n;i++)
if(x[i]!=1) {x[i]=1; return;}
//从遇到的第⼀位开始,若是0,将其变成1,然后结束for循环,得到⼀种解法
else x[i]=0;
return;
//从第⼀位开始,若是1,将其变成0,然后继续循环,若再循环的时候遇到0,则将其变为1,结束循环。得到另⼀种解法。
}
虽然我现在也不知道为什么会这样,但是确实是个很好的规律,找到这个规律后,就可以很轻松的⾃⼰写出各种排列情况,以后遇到排列的问题,就⽤这个⽅法。语⾔不好描述,上图⽚演⽰(是歪的,凑活看吧。。。):
(2)算法思想:
x[i]的值为0/1,即选或者不选
w[i]的值表⽰商品i的重量
v[i]的值表⽰商品的价值
所以这个算法最核⼼的公式就是
tw=x[1]*w[1]+x[2]*w[2]+.......+x[n]*w[n]
tv=x[1]*w[1]+x[2]*v[2]+......+x[n]*v[n]
tv1:⽤于存储当前最优解
limit:背包容量
浅谈0-1背包问题的常用算法
0 - 1背包 问题是背包 问题 的一个 特例 ,二 者的 区别在 于 物品装入 背包 过程 中是否可 以部分装入 ;可 以部分装入 的属 于背包 问题研 究范畴 ,不可 以部 分装入 的背包 问题 可 以描述 为0 - 1 背包 问题 。0 - 1背包 问题的应用广泛 ,许多的实 际问题 都可 以转化为 0 - 1 背包 问题 。例如:贷款组合优化决策问题 、 项 目投资问题、预算控制、货物装载等 。所以,O — l背包 问题 的算法研究无论是在理论上还是在实践 中都具有深远 的意义 。 0 - 1 背 包问题 的抽象模型描述 ( 一 )0 - 1 背包 问题 描述 。给 定 n个物 品,这 n个物 品 的重量 分别 为 { w 1 ,w 2 ,… ,w n } ,这 n个物 品的价值 分 别 为 { v 1 ,v 2 ,… ,v n ) , 有 ~ 个 容 量 为 C的背 包 ,如 何 选 择 装 入背包 的物 品,使得装入背包 中物 品的总价值最大 ,对 于 每种物品只有两种 选择 :装入背包或不装入背包 。 ( 二 )抽象模型描述
消 费 电子
2 0 1 3年 1 0月下 C o n s u me r E l e c t r o n i c s Ma g a z i n e 技 术 交 流
浅谈 0 - 1 背包问题的常用算法
汤赫 男
蛮力法、动态规划法、回溯法和分支限界法求解01背包问题
一、实验内容:
分别用蛮力法、动态规划法、回溯法和分支限界法求解0/1背包问题。
注:0/1背包问题:给定n种物品和一个容量为C的背包,物品i的重量是w
i,其价值为v
i,背包问题是如何使选择装入背包内的物品,使得装入背包中的物品的总价值最大。其中,每种物品只有全部装入背包或不装入背包两种选择。
二、所用算法的基本思想及复杂度分析:
1.蛮力法求解0/1背包问题:
1)基本思想:
对于有n种可选物品的0/1背包问题,其解空间由长度为n的0-1向量组成,可用子集数表示。在搜索解空间树时,深度优先遍历,搜索每一个结点,无论是否可能产生最优解,都遍历至叶子结点,记录每次得到的装入总价值,然后记录遍历过的最大价值。
2)代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100 //最多可能物体数
struct goods//物品结构体
{
int sign;//物品序号
int w; //物品重量
int p; //物品价值
}a[N];
bool m(goods a,goods b)
{
return (a.p/a.w)>(b.p/b.w);
}
int max(int a,int b)
{
return a<b?b:a;
}
int n,C,bestP=0,cp=0,cw=0;
int X[N],cx[N];
/*蛮力法求解0/1背包问题*/
int Force(int i)
{
if(i>n-1){
if(bestP<cp&&cw+a[i].w<=C){
利用动态规划解决01背包问题01背包问题动态规划
利用动态规划解决01背包问题01背包问题动态规
划
背包问题是一个经典的动态规划模型,很多关于算法的教材都把它作为一道例题,该问题既简单又容易理解,而且在某种程度上还能够揭示动态规划的本质。
将具有不同重量和价值的物体装入一个有固定载重量的背包,以获取最大价值,这类问题被称为背包问题。
背包问题可以扩展出很多种问题,而01背包问题是最常见、最有代表性的背包问题。
一、问题描述
给定一个载重量为M的背包及n个物体,物体i的重量为wi、价值为pi,1≤i≤n,要求把这些物体装入背包,使背包内的物体价值总量最大。此处我们讨论的物体是不可分割的,通常称这种物体不可分割的背包问题为01背包问题。
二、基本思路
01背包问题的特点是:每种物体只有一件,可以选择放或者不放。假设:xi表示物体i被装入背包的情况,xi=0,1。当xi=0时,表示物体没有被装入背包;当xi=1时,表示物体被装入背包。根据问题的要求,有如下的约束方程(1)和目标函数(2):
三、利用动态规划法求解01背包问题
(一)动态规划算法的基本思想
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,
经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中,这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
分支限界法解01背包问题
分支限界法解01背包问题(总12
页)
--本页仅作为文档封面,使用时请直接删除即可--
--内页可以根据需求调整合适字体及大小--
分支限界法解01背包问题
学院:网研院姓名:XXX 学号:2013XXXXXX 一、分支限界法原理
分支限界法类似于回溯法,也是在问题的解空间上搜索问题解的算法。一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出解空间中满足约束条件的所有解;而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
由于求解目标不同,导致分支限界法与回溯法对解空间的搜索方式也不相同。回溯法以深度优先的方式搜索解空间,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间。
分支限界法的搜索策略是,在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一扩展结点。为了有效地选择下一扩展结点,加速搜索的进程,在每一个活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。
常见的分支限界法有如下两种:
队列式(FIFO)分支限界法:按照先进先出原则选取下一个节点为扩展节点。活结点表是先进先出队列。FIFO分支限界法搜索策略:
一开始,根结点是唯一的活结点,根结点入队。
从活结点队中取出根结点后,作为当前扩展结点。
对当前扩展结点,先从左到右地产生它的所有儿子,用约束条件检查,
蛮力法、动态规划法 求解01背包问题
#include <iostream>
#include <vector>
using namespace std;
void MFKnapsack(int capacity, int *values, int *weights,
vector<int> &c, int d, int &max_value)
MFKnapsack(capacity,values,weights,c,0,max_value);
return max_value;
}
int main()
{
int capacity=10,n=7;
int values[]={6,3,5,4,6,3,10};
int weights[]={1,2,5,5,4,4,6};
cin>>m;
cout<<"请输入物品的总个数:"<<endl;
cin>>n;
cout<<"旅行者背包能装的最大总价值为:"<<MFknapsack(m,n)<<endl;
return 0;
}
五、运行输出结果:
(1)Brute Force:
(2)Dynamic Programming:
用蛮力法、动态规划法和贪心法求解0 1背包问题
背包问题至少有三种看似合理的贪心策略:
(1)选择价值最大的物品,因为这可以尽可能快地增加背包的总价值。但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗得太快,使得装入背包的物品个数减少,从而不能保证目标函数达到最大。
{
int n;//物品的编号
int w;ቤተ መጻሕፍቲ ባይዱ/物品的重量
int v;//物品的价值
}wup;
wupwp[N];//物品的数组,N为物品的个数
void inputwp(wup*p)//输入函数
{
int i;//i为物品的个数
for (i=0;i<N;i++)//for循环物品的个数,总的物品有N个
{
printf("\n请输入第%d个物品的编号、重量、价值",i);
V(i, 0)=V(0,j)=0(式3)jw
V(i1,j)
V(i,j)
i(式4)max{V(i1,j),V(i1,jw
i)v
i}jw
i
式3表明:把前面i个物品装入容量为0的背包和把0个物品装入容量为j的背包,得到的价值均为0。式4的第一个式子表明:如果第i个物品的重量大于背包的容量,则装入前i个物品得到的最大价值和装入前i-1个物品得到的最大价值是相同的,即物品i不能装入背包;第二个式子表明:如果第i个物品的重量小于背包的容量,则会有以下两种情况:(1)如果把第i个物品装入背包,则背包中物品的价值等于把前i-1个物品装入容量为j-wi的背包中的价值加上第i个物品的价值vi;(2)如果第i个物品没有装入背包,则背包中物品的价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值较大者作为把前i个物品装入容量为j的背包中的最优解。
动态规划算法--01背包问题
动态规划算法--01背包问题
基本思想:
动态规划算法通常⽤于求解具有某种最优性质的问题。在这类问题中,可能会有许多可⾏解。每⼀个解都对应于⼀个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若⼲个⼦问题,先求解⼦问题,然后从这些⼦问题的解得到原问题的解。与分治法不同的是,适合于⽤动态规划求解的问题,经分解得到⼦问题往往不是互相独⽴的(即下⼀个⼦阶段的求解是建⽴在上⼀个⼦阶段的解的基础上,进⾏进⼀步的求解)。若⽤分治法来解这类问题,则分解得到的⼦问题数⽬太多,有些⼦问题被重复计算了很多次。如果我们能够保存已解决的⼦问题的答案,⽽在需要时再找出已求得的答案,这样就可以避免⼤量的重复计算,节省时间。我们可以⽤⼀个表来记录所有已解的⼦问题的答案。不管该⼦问题以后是否被⽤到,只要它被计算过,就将其结果填⼊表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
应⽤场景:
适⽤动态规划的问题必须满⾜最优化原理、⽆后效性和重叠性。
1、最优化原理(最优⼦结构性质)最优化原理可这样阐述:⼀个最优化策略具有这样的性质,不论过去状态和决策如何,对前⾯的决策所形成的状态⽽⾔,余下的诸决策必须构成最优策略。简⽽⾔之,⼀个最优化策略的⼦策略总是最优的。⼀个问题满⾜最优化原理⼜称其具有最优⼦结构性质。
2、⽆后效性将各阶段按照⼀定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态⽆法直接影响它未来的决策,⽽只能通过当前的这个状态。换句话说,每个状态都是过去历史的⼀个完整总结。这就是⽆后向性,⼜称为⽆后效性。
算法背包问题的五种方法
算法背包问题的五种方法
1. 动态规划
背包问题是一种经典的组合优化问题,动态规划是解决背包问题的常用方法之一。动态规划将问题分解为子问题,并利用已解决子问题的结果来求解更大规模的问题。对于背包问题,动态规划算法的基本思想是创建一个二维数组dp,其中
dp[i][j]表示在前i个物品中选择若干个物品放入容量为j的背包中所能获得的最大价值。通过填表格的方式,从子问题逐步求解到原问题,最终得到最优解。
2. 贪心算法
贪心算法是另一种解决背包问题的方法。它的基本思想是每一步都选择当前看起来最好的选择,而不考虑之前的选择对后续步骤的影响。在背包问题中,贪心算法通常是按照物品的价值密度(价值与重量的比值)进行排序,然后依次选择价值密度最高的物品放入背包,直到背包容量不足为止。贪心算法的优势在于其简单性和高效性,但它并不一定能得到最优解。
3. 分支定界法
分支定界法是一种通过搜索方式求解背包问题的方法。它的基本思想是通过搜索可能的解空间,并根据当前搜索路径的特性进行剪枝操作,从而减少搜索的时间和空间复杂度。在背包问题中,分支定界法通常根据当前节点的上界(通过松弛问题得到)与当前最优解进行比较,如果上界小于当前最优解,则该节点不再继续拓展,从而减少搜索空间的大小,提高求解效率。
4. 回溯算法
回溯算法是一种通过不断试探和回退的方式求解背包问题的方法。它的基本思想是从问题的初始状态开始,不断地尝试不同的决策,并根据约束条件判断该决策是否可行。如果决策可行,则继续尝试下一步决策;如果不可行,则回退到上一步
并尝试其他决策。在背包问题中,回溯算法通过递归的方式依次尝试每个物品的放入与不放入两种选择,直到找到满足约束条件的解或者穷尽所有可能。
蛮力法等求解背包问题报告剖析
算法综合实验报告
学号:姓名:
一、实验内容:
分别用蛮力、动态规划、贪心及分支限界法实现对TSP问题或者0-1背包问题的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。
二、程序设计的基本思想、原理和算法描述:
1、蛮力法
(1)数据结构:
使用一维数组存储物品的价值和重量还有下标。
(2)函数组成
除主函数外还有一个subset()函数,在此函数中列出所有的子集列出子集的同时求解最大价值,并且物品总重量要小于背包总容量。
(3)输入/输出设计
首先通过键盘输入物品的总重量,再输入背包总容量,依次输入每个物品的重量,对应输入相应重量的价值,循环直至输入所有物品的重量和价值。最后输出物品的最大价值。
本程序通过键盘进行输入、屏幕进行输出。
(根据实际程序情况,还可以选择随机产生输入数据、将输出数据输出到文件等其它方式)
(4)符号名说明
w[1001]为物品重量的集合,v[1001]为物品价值的集合,n为物品数量,m为背包总容量,x[1001]用来存储物品是否装入背包,0为不装入,1为装入。用a[1001]来存储下标,用下标找出所有子集。
(5)算法描述
采用增量构造的方法来构造出物品的所有子集,对物品的下标应用此方法进行构造,下标与物品相对应,选出子集时物品的重量加之前重量
小于背包总重量时将价值加上去,最后选出能装入背包的物品的最大值。
2、 动态规划法
(1)数据结构:
使用一维数组存储各个物品价值,重量,使用一个二维数组存储动态规划的整体求解的表,并以背包容量为最大列号,物品个数为最大行号。
(2)函数组成:
分支限界法 01背包问题c语言
分支限界法 01背包问题c语言
分支限界法是一种解决组合优化问题的算法。其中,01背包问题是一种经典的背包问题,它要求在给定的容量下,选择商品的组合,使得组合的总价值达到最大化,但组合中每种商品只能选择一次。
C语言是一种广泛使用的编程语言,适用于实现各种算法和数据结构。下面我将用C语言实现分支限界法来解决01背包问题。
首先,我们定义一个结构体用来表示商品的信息,包括商品的重量和价值:
```
typedef struct {
int weight;
int value;
} Item;
```
接下来,我们定义一个递归函数来实现分支限界法。该函数通过深度优先搜索的方式,尝试不同的选择,并计算当前组合的总价值。如果当前组合的总价值已经超过了已知的最优解,则剪枝,不再继续搜索。
```
void branchAndBound(int index, int capacity, int currentWeight, int currentValue, int n, Item items[], int bestValue, int choice[]) {
if (index >= n || currentWeight >= capacity) {
if (currentValue > bestValue) {
bestValue = currentValue;
// 更新最优解
for (int i = 0; i < n; i++) {
choice[i] = tempChoice[i];
}
}
return;
蛮力法解决0_1背包问题新思路-——利用C语言位域类型
蛮⼒法解决0_1背包问题新思路-——利⽤C语⾔位域类型废话不说了,直接上代码
#include<stdio.h>
#include<math.h>
#define N 5 //物品种类数⽬
#define CAPACITY 6 //背包容量
#define COUNT 32
int weight[N]={3,2,1,4,5};
int value[N]={25,20,15,40,50};
union{
unsigned char state;
struct _FLAG{
unsigned char good_1_flag:1;
unsigned char good_2_flag:1;
unsigned char good_3_flag:1;
unsigned char good_4_flag:1;
unsigned char good_5_flag:1;
}flags;
}package;
int function()
{
int sunw=0,sumv=0,maxValue=0;
int totalWeight=0,totalValue=0,position,state;
for(state=0;state<COUNT;state++)
{
package.state=state;
totalWeight=package.flags.good_1_flag*weight[0]+package.flags.good_2_flag*weight[1]
+package.flags.good_3_flag*weight[2]+package.flags.good_4_flag*weight[3]
蛮力法、动归、贪心、分支限界法解01背包问题
算法综合实验报告
一、实验内容:
分别用蛮力、动态规划、贪心及分支限界法实现对0-1背包问题的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。
二、程序设计的基本思想、原理和算法描述:
1、蛮力法
1.1数据结构
注:结构体obj用来存放单个物品的价值和重量
typedef struct obj
{
int w;//物品的重量
int v;//物品的价值
};
1.2 函数组成
void subset(int s[][10],int n):用来生成子集的函数
void judge(int s[][10], obj obj[],int mark[],int n,int c):判断子集的可行性
int getmax(int mark[],int n,int &flag):求解问题的最优解
void outputObj(int flag,int s[][10],int n):输出选择物品的情况 1.3 输入/输出设计
本程序通过键盘进行输入、屏幕进行输出。
1.4 符号名说明
1.5 算法描述
算法的伪代码描述如下:
输入:背包的容量c,物品的个数n,n个物品的重量 w[n],价值v[n]
输出:装入背包的物品编号以及产生的最大价值
1.初始化最大价值 max=0,结果子集 s=φ;
2.对集合{1,2,......n}的每一个子集T,执行下述操作:
2.1初始化背包的价值 v=0,背包的重量 w=0;
2.2对子集t的每一个元素j
2.2.1 如果w+wj<c,则 w=w+wj,v=v+vj;
2.2.2 否则,转步骤2考察下一个子集;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法综合实验报告
学号: 1004121206 姓名:林
一、实验内容:
分别用蛮力、动态规划、贪心及分支限界法实现对0-1背包问题的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。
二、程序设计的基本思想、原理和算法描述:
1、蛮力法
1.1数据结构
注:结构体obj用来存放单个物品的价值和重量
typedef struct obj
{
int w;//物品的重量
int v;//物品的价值
};
1.2 函数组成
void subset(int s[][10],int n):用来生成子集的函数
void judge(int s[][10], obj obj[],int mark[],int n,int c):判断子集的可行性
int getmax(int mark[],int n,int &flag):求解问题的最优解
void outputObj(int flag,int s[][10],int n):输出选择物品的情况 1.3 输入/输出设计
本程序通过键盘进行输入、屏幕进行输出。
1.4 符号名说明
符号说明
S[][]存放子集
mark[]记录子集的可行性
n物品的个数
c物品的容量
max记录背包所能产生的最大价值
flag记录能产生最大价值的子集的编号
1.5 算法描述
算法的伪代码描述如下:
输入:背包的容量c,物品的个数n,n个物品的重量 w[n],价值v[n]
输出:装入背包的物品编号以及产生的最大价值
1.初始化最大价值 max=0,结果子集 s=φ;
2.对集合{1,2,......n}的每一个子集T,执行下述操作:
2.1初始化背包的价值 v=0,背包的重量 w=0;
2.2对子集t的每一个元素j
2.2.1 如果w+wj 2.2.2 否则,转步骤2考察下一个子集; 2.3如果max 3.输出子集S中的各元素 2、动态规划法 2.1 数据结构 该程序不涉及任何数据结构 2.2 函数组成 int max(int i,int j);比较并返回两个数中的较大值 int KnapSack (int w[],int v[],int x[],int n,int c);求解背包取得的最大值 2.3 输入/输出设计 本程序通过键盘进行输入、屏幕进行输出。 2.4 符号名说明 符号说明 n物品的个数 c物品的容量 w[] 物品的重量 v[] 物品的价值 x[] 物品的选择情况 V[][] 存放迭代结果 2.5 算法描述 算法的伪代码描述如下: 输入:背包的容量c,物品的个数n,n个物品的重量 w[n],价值v[n] 输出:装入背包的物品标号和背包获得的最大价值 1.初始化二维数组V[][]={0} 2.初始化二维数组的第0行,第0列 2.循环直到i==n 2.1 循环直到j=c 2.1.1 如果背包的容量不足以装入物品i,则装入前i个物品得 到的最大价值和装入前i-1个物品得到的最大价值相等 2.2.2 如果背包的容量可以装入物品i,分别计算装入物品i可 达到的价值量V[i-1][j-w[i]]+v[i],以及不放入物品i可以得到的最大价值V[i-1][j],取二者中的较大者作为把前i个物品装入容量为j的背包中的最优解 3、贪心法 3.1数据结构 注:结构体用来存放物品的重量、价值、单位价值、物品编号等信息 struct _Object { int Value;//物品价值 int Weight;//物品重量 double AveValue;//物品单位价值 double Num;//物品可以放入的数量 int key;//物品标号 }; 3.2 函数组成 int Partition(_Object r[],int first,int end);以数组第一个元素为准对数组进行一次划分并返回基准元素的位置坐标 void QuickSort(_Object r[],int first,int end);快速排序 double knaspsack(int n,int M,_Object object[]);求解背包问题的最优解 3.3 输入/输出设计 本程序通过键盘进行输入、屏幕进行输出。 3.4 符号名说明 符号说明 n物品的个数 c物品的容量 pro[] 物品的重量、价值、单位价值、编号 3.5 算法描述 算法的伪代码描述如下: 输入:背包的容量c,物品的个数n,n个物品的重量 pro[n].Weight,价值pro[n].Value 输出:装入背包的物品标号和背包获得的最大价值 1.计算物品的单位价值并存入pro[n]. 2.将物品按照单位价值递减的顺序进行排序 3.i=0; 4.循环直到(object[i].Weight>c) 4.1 将第i个物品放入背包,object[i].Num=1; 4.2 c-=pro[n].Weight; 4.3 i++; 5.记录最后放入背包的物品的重量: object[i].Num=(double)C/object[i].Weight; 4、分支限界法 4.1数据结构 注:物品结构体,存放物品价值、重量、单位价值、物品编号等信息 struct obj { int v;//物品价值 int w;//物品重量 double avg;//物品单位价值 int id;//物品编号 }; 注:结构体node用来存放节点表节点 struct node { node *parent,//父亲结点指针 *next;//后继结点指针 int level,//节点所处的层 isin,//记录物品是否装入背包,0代表不装,1代表装入 cw,//当前背包已经装入的物品重量 cv;//当前背包已经装入的物品价值 double ub;//结点的上界值 };