第4章 贪心算法实验指导

第4章 贪心算法实验指导
第4章 贪心算法实验指导

第4章贪心算法

实验4.1 贪心算法的实现与时间复杂度测试

1. 实验目的

编程实现经典的贪心算法,理解贪心算法设计的基本思想、程序实现的相关技巧,加深对贪心算法设计与分析思想的理解。通过程序的执行时间测试结果,与理论上的时间复杂度结论进行对比、分析和验证。

2. 原理解析

贪心算法的基本思想

贪心算法求解优化问题的基本思想是:采用逐步构造最优解的方法。在每个阶段,都做出一个当前最优的决策(在一定的标准下)。决策一旦做出,就不可再更改(做出贪心决策的依据称为贪心准则)。贪心算法的一般步骤如下:

(1) 根据拟解决问题选取一种贪心准则;

(2) 按贪心准则标准对n个候选输入排序(以这一方法为代表,仍可基于堆来存储候选);

(3) 依次选择输入量加入部分解中:如果当前这个输入量的加入,不满足约束条件,则不把此输入加到这部分解中。

贪心算法的基本设计范式如下:

Greedy(A,n)

A: include n inputs

Solution=Ф

for i=1 to n do

x=Select(A)

if Feasible(solution,x) then

solution=Union(solution,x)

end if

end for

return solution

测试算法

背包问题是使用贪心算法求解的代表问题,算法如下:

KnapsackGreedy(p,w,m,x,n)

//v[1..n]和w[1..n]分别含有按vi/wi v(i+1)/v(i+1)排序的n 件物品的价值和重量。M是背包的容量大小,而x[1..n]是解向量// for i=1 to n do

xi=0 //将解向量初始化为零//

end for

cu=m //cu是背包剩余容量//

for i=1 to n do

if wi>cu then

exit

end if

xi=1

cu=cu-wi

repeat

if i≤n then

xi=cu/wi

end if

算法的时间复杂度取决于对v i/w i排序的时间复杂度,例如,若选择MergeSort 排序算法,则以上算法的时间复杂度为O(n log n)。

3. 实验内容

(1)编程实现以上求解背包问题的贪心算法,并通过手动设置、生成随机数获得实验数据。记录随着输入规模增加算法的执行时间,分析并以图形方式展现增长率;测试、验证、对比算法的时间复杂度。

(2)利用贪心算法思想,设计实现单源最短路径问题的算法,并编程实现。

4. 实验步骤和要求

实验内容(1)步骤:

(1) 编程实现以上KnapsackGreedy算法,并进行测试,保证程序正确无误。

其中,分别在程序开始和结束处设置记录系统当前时间的变量、用于计算程序执行的时间(以毫秒(ms)作为时间的计数单位)。

(2) 设定一个m值(背包容量),测试随着n增加、程序执行时间增加的趋势。分别使用实验1中的随机数生成算法生成n个随机数作为n个物品的重量,再生成n个随机数作为n个物品的价值(n=10, 20, 40, 100, 200, 400, 800, 2000)。记录随着n增加程序的执行时间,并使用MS Excel图表绘制工具生成程序执行时间的对比曲线图。

(3) 与理论上的时间复杂度结论进行对比分析,完成实验报告。

实验内容(2)步骤:

(1)分析该问题的贪心选择性质;

(2)分析该问题的最优子结构性质;

(3)算法的设计与实现;

回溯法实验(0-1背包问题)

算法分析与设计实验报告第五次附加实验

附录: 完整代码(回溯法) //0-1背包问题回溯法求解 #include using namespace std; template class Knap //Knap类记录解空间树的结点信息 { template friend Typep Knapsack(Typep [],Typew [],Typew,int); private: Typep Bound(int i); //计算上界的函数 void Backtrack(int i); //回溯求最优解函数

Typew c; //背包容量 int n; //物品数 Typew *w; //物品重量数组| Typep *p; //物品价值数组 Typew cw; //当前重量 Typep cp; //当前价值 Typep bestp; //当前最后价值 }; template Typep Knapsack(Typep p[],Typew w[],Typew c,int n); //声明背包问题求解函数template inline void Swap(Type &a,Type &b); //声明交换函数 template void BubbleSort(Type a[],int n); //声明冒泡排序函数 int main() { int n ;//物品数 int c ;//背包容量 cout<<"物品个数为:"; cin>>n; cout<<"背包容量为:"; cin>>c; int *p = new int[n];//物品价值下标从1开始 int *w = new int[n];//物品重量下标从1开始 cout<<"物品重量分别为:"<>w[i]; } cout<<"物品价值分别为:"<>p[i]; } cout<<"物品重量和价值分别为:"<

回溯法实验(最大团问题)

算法分析与设计实验报告第七次附加实验

} } 测试结果 当输入图如下时: 当输入图如下时: 1 2 3 4 5 1 2 3 4 5

当输入图如下时: 1 2 3 4 5

附录: 完整代码(回溯法) //最大团问题回溯法求解 #include using namespace std; class Clique { friend void MaxClique(int **,int *,int ); private: void Backtrack(int i); int **a; //图的邻接矩阵 int n; //图的顶点数 int *x; //当前解 int *bestx; //当前最优解 int cn; //当前顶点数 int bestn; //当前最大顶点数 }; void Clique::Backtrack(int i) { //计算最大团 if(i>n) //到达叶子节点 { for(int j=1;j<=n;j++) bestx[j]=x[j]; bestn=cn;

cout<<"最大团:("; for(int i=1;i=bestn) { //修改一下上界函数的条件,可以得到 x[i]=0; //相同点数时的解 Backtrack(i+1); } } void MaxClique(int **a,int *v,int n) { //初始化Y Clique Y; Y.x=new int[n+1]; Y.a=a; Y.n=n; https://www.360docs.net/doc/1c3104031.html,=0; Y.bestn=0; Y.bestx=v; Y.Backtrack(1); delete [] Y.x; cout<<"最大团的顶点数:"<

第四章-贪心算法(模拟试题)

计算机与信息科学学院2010-2011学年第2学期模拟试卷 计算机算法设计与分析—第四章.贪心算法 本卷满分100分 完卷时间120分钟 一. 简答题(每小题2分,共20分) 1. 当一个问题具有 且具有 时可用贪心算法,如最小生成树问题(背包问题,活动安排问题等)。 2. 在动态规划可行的基础上满足 才能用贪心。 3. 贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的 选择。 4. 动态规划算法通常以 的方式解各子问题,而贪心算法则通常 以 的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题 5. 贪心算法和动态规划算法都要求问题具有 性质,这是2类算法的一个共同点。 6. 当一个问题的最优解包含其子问题的最优解时,称此问题具有 。 7. 对于具有n 个顶点和e 条边的带权有向图,如果用带权邻接矩阵表示这 个图,那么Dijkstra 算法的主循环体需要 时间。这个循环需要执行n-1次,所以完成循环需要 时间。算法的其余部分所需要时间不超过 。 8. 0-1背包问题指:给定n 种物品和一个背包。物品i 的重量是Wi ,其价值为Vi ,背包的容量为C 。应如何选择装入背包的物品,使得装入背包中物品的 最大。 9. 有一批集装箱要装上一艘载重量为c 的轮船。其中集装箱i 的重量为Wi 。最优装载问题要求确定在 不受限制的情况下,将 装上轮船。 10. 多机调度问题要求给出一种作业调度方案,使所给的n 个作业在 由m 台机器加工处理完成。 二. 综合题(1-6题每题7分,7-8题每题9分,共60分) 1. 有4个物品,其重量分别为(4, 7, 5, 3),物品的价值分别为(40, 42, 25, 12),背包容量为10。试设计3种贪心策略,并给出在每种贪心策略下背包问题的解。 )(n O

算法设计与分析:回溯法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目回溯算法 实验评分表

实验报告 一、实验目的与要求 1、理解回溯算法的基本思想; 2、掌握回溯算法求解问题的基本步骤; 3、了解回溯算法效率的分析方法。 二、实验内容 【实验内容】 最小重量机器设计问题:设某一个机器有n个部件组成,每个部件都可以m个不同供应商处购买,假设已知表示从j个供应商购买第i个部件的重量,表示从j个供应商购买第i个部件的价格,试用回溯法求出一个或多个总价格不超过c且重量最小的机器部件购买方案。 【回溯法解题步骤】 1、确定该问题的解向量及解空间树; 2、对解空间树进行深度优先搜索; 3、再根据约束条件(总价格不能超过c)和目标函数(机器重量最小)在搜索过程中剪去多余的分支。 4、达到叶结点时记录下当前最优解。 5、实验数据n,m, ] ][ [j i w,] ][ [j i c的值由自己假设。 三、算法思想和实现【实现代码】

【实验数据】 假设机器有3个部件,每个部件可由3个供应商提供(n=3,m=3)。总价不超过7(c<=7)。 部件重量表: 部件价格表: 【运行结果】

实验结果:选择供应商1的部件1、供应商1的部件2、供应商3的部件3,有最小重量机器的重量为4,总价钱为6。 四、问题与讨论 影响回溯法效率的因素有哪些? 答:影响回溯法效率的因素主要有以下这五点: 1、产生x[k]的时间; 2、满足显约束得x[k]值的个数; 3、计算约束函数constraint的时间; 4、计算上界函数bound的时间; 5、满足约束函数和上界函数约束的所有x[k]的个数。 五、总结 这次实验的内容都很有代表性,通过上机操作实践与对问题的思考,让我更深层地领悟到了回溯算法的思想。 回溯算法的基本思路并不难理解,简单来说就是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。回溯法的基本做法是深度优先搜索,是一种组织得井井

第四章贪心算法

第四章贪心算法 一、课本+作业 DIJKSTRA的主要思想 算法的思想是把中心定在起始顶点,向外层结点扩展,最终在目标顶点结束,停止扩展。设顶点集合为S,通过贪心选择,逐步扩充这个集合。一开始,集合S中所包含顶点仅为源点。设u为图G的某一结点,把从开始顶点到结点u,且中间经过的顶点均在集合S内的线路称为从源点到u的特殊路径。 创建一个数组SD,用于储存每个顶点所对应的最短特殊路径的长度。算法每次从u∈V-S 中取出具有最短特殊路长度的顶点u,将u添加到集合S中,与此同时,修改数组SD。当S包含了所有V中顶点时,SD就记录了从源到所有其它顶点之间的最短路径长度。 Dijkstra算法的时间复杂度为O(n2),空间复杂度随着选择的存储方式不同而有所变化,若存储方式为邻接矩阵时为O(n2)。在求解单源最短路径问题时,Dijkstra算法可以得到最优解,但由于它需要遍历众多结点,所以效率低。

历年试题 1.(2011年)试用Prim算法求解下面无向赋权图的最小生成树,指出最小生成树及该树中各边被选中的先后次序;写出算法的基本步骤。

2. (2010)1.分析Kruskal 算法的时间复杂度; 2. 试用下面的例子说明用Kruskal 算法求解最优生成树问题,并总结出算法的 基本步骤: 3.(2009)(原理习题有) 4. (2006) 设n p p p ,,,21 是准备存放到长为L 的磁带上的n 个程序,程序i p 需要的带 长为i a 。设L a n i i >∑=1,要求选取一个能放在带上的程序的最大子集合(即其中含有 最多个数的程序)Q 。构造Q 的一种贪心策略是按i a 的非降次序将程序计入集合。 1). 证明这一策略总能找到最大子集Q ,使得∑∈≤Q p i i L a 。

算法分析与设计实验四回溯法

实验四 回溯法 实验目的 1. 掌握回溯法的基本思想方法; 2. 了解适用于用回溯法求解的问题类型,并能设计相应回溯法算法; 3. 掌握回溯法算法复杂性分析方法,分析问题复杂性。 预习与实验要求 1. 预习实验指导书及教材的有关内容,掌握回溯法的基本思想; 2. 严格按照实验内容进行实验,培养良好的算法设计和编程的习惯; 3. 认真听讲,服从安排,独立思考并完成实验。 实验设备与器材 硬件:PC 机 软件:C++或Java 等编程环境 实验原理 回溯法是最常用的解题方法,有“通用的解题法”之称。当要解决的问题有若干可行解时,则可以在包含问题所有解的空间树中,按深度优先的策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的搜索,继续查找该结点的兄弟结点,若它的兄弟结点都不包含问题的解,则返回其父结点——这个步骤称为回溯。否则进入一个可能包含解的子树,继续按深度优先的策略进行搜索。这种以深度优先的方式搜索问题的解的算法称为回溯法。它本质上是一种穷举法,但由于在搜索过程中不断略过某些显然不合适的子树,所以搜索的空间大大少于一般的穷举,故它适用于解一些组合数较大的问题。 回溯法也可以形式化地描述如下:假设能够用n 元组()n i x x x x ,,,,,21 表示一个给定问题P 的解,其中i i S x ∈。如果n 元组的子组()i x x x ,,,21 ()n i <满足一定的约束条件,则称为部分解。如果它已经是满足约束条件的部分解,则添加11++∈i i S x 形成新的子组()121,,,,+i i x x x x ,并检查它是否满足约束条件,若仍满足则继续添加22++∈i i S x ,并以此类推。如果所有的11++∈i i S x 都不满足约束条件,那么去掉1+i x ,回溯到i x 的位置,并去掉当前的i x ,另选一个i i S x ∈',组成新的子组()i x x x ',,,21 ,并判断其是否满足约束条件。如此反复下去,直到得到解或者证明无解为止。

回溯法实验(最优装载)

算法分析与设计实验报告第二次附加实验 )用可行性约束函数可剪去不满足约束条件

附录: 完整代码(贪心法) //回溯法递归求最优装载问题#include #include #include using namespace std; template class Loading { public: void Backtrack(int i);

int n, //集装箱数 *x, //当前解 *bestx; //当前最优解 Type *w, //集装箱重量数组 c, //第一艘轮船的载重量 cw, //当前载重量 bestw, //当前最优载重量 r; //剩余集装箱重量 }; template void Loading::Backtrack(int i); template //参数为:w[]各物品重量数组,c为第一艘轮船的载重量,n为物品数量,bestx[]数组为最优解 Type MaxLoading(Type w[],Type c,int n,int bestx[]); int main() { int n=3,m; int c=50,c2=50; int w[4]={0,10,40,40}; int bestx[4]; clock_t start,end,over; //计算程序运行时间的算法 start=clock(); end=clock(); over=end-start; start=clock(); m=MaxLoading(w,c,n,bestx); //调用MaxLoading函数 cout<<"轮船的载重量分别是:"<>n; cout<<"位置排列是:"<0) { a[k]=a[k]+1; while((a[k]<=n) && (check(k)==0)) a[k]=a[k]+1; if(a[k]<=n) if(k==n) { num++; output(n); } else { k=k+1; a[k]=0; } else k=k-1; } cout<<"一共有"<

算法分析习题参考答案第四章

第四章作业 部分参考答案 1. 设有n 个顾客同时等待一项服务。顾客i 需要的服务时间为n i t i ≤≤1,。应该如何安排n 个顾客的服务次序才能使总的等待时间达到最小?总的等待时间是各顾客等待服务的时间的总和。试给出你的做法的理由(证明)。 策略: 对 1i t i n ≤≤进行排序,,21n i i i t t t ≤≤≤ 然后按照递增顺序依次服务12,,...,n i i i 即可。 解析:设得到服务的顾客的顺序为12,,...,n j j j ,则总等待时间为 ,2)1(121n n j j j j t t t n nt T +++-+=- 则在总等待时间T 中1j t 的权重最大,jn t 的权重最小。故让所需时间少的顾客先得到服务可以减少总等待时间。 证明:设,21n i i i t t t ≤≤≤ ,下证明当按照不减顺序依次服务时,为最优策略。 记按照n i i i 21次序服务时,等待时间为T ,下证明任意互换两者的次序,T 都不减。即假设互换j i ,)(j i <两位顾客的次序,互换后等待总时间为T ~ ,则有 .~ T T ≥ 由于 , ))(())(()2)(2()1)(1(21n j i i i i i i t j t j n i t i n t n t n T +--++--++--+--=,))(())(()2)(2()1)(1(~ 21n i j i i i i i t j t j n i t i n t n t n T +--++--++--+--= 则有 .0))((~ ≥--=-i j i i t t i j T T 同理可证其它次序,都可以由n i i i 21经过有限次两两调换顺序后得到,而每次交换,总时间不减,从而n i i i 21为最优策略。 2. 字符h a ~出现的频率分布恰好是前8个Fibonacci 数,它们的Huffman 编码是什么?将结果推广到n 个字符的频率分布恰好是前n 个Fibonacci 数的情形。Fibonacci 数的定义为:1,1,11210>+===--n if F F F F F n n n

回溯法解0 1背包问题实验报告

实验4 回溯法解0-1背包问题 一、实验要求 1.要求用回溯法求解0-1背包问题; 要求交互输入背包容量,物品重量数组,物品价值数组;2.要求显示结果。3. 二、实验仪器和软件平台 仪器:带usb接口微机 软件平台:WIN-XP + VC++ 三、实验源码 #include \ #include #include #include<> #include using namespace std; template class Knap { public: friend void Init(); friend void Knapsack(); friend void Backtrack(int i); friend float Bound(int i); bool operator<(Knap a)const { if(fl< return true; else return false; } private: ty w; ; cout<>bag[i].v; for(i=0;i

{ bag[i].flag=0; bag[i].kk=i; bag[i].fl=*bag[i].v/bag[i].w; } }void Backtrack(int i){cw+=bag[i].w;if(i>=n) <=c) lag=1; cp+=bag[i].v; Backtrack(i+1); cw-=bag[i].w; cp-=bag[i].v; } if(Bound(i+1)>bestp)lag=0; Backtrack(i+1); }}<=cleft){; b+=bag[i].v; i++; } /bag[i].w * cleft; return b; } void Knapsack() k]=bag[k].flag; lag*bag[k].v; //价值累加 } cout<

ch4_贪心算法

78 第四章 贪心算法 §1.贪心算法基本思想 找零钱 假如售货员需要找给小孩67美分的零钱。现在,售货员手中只有25美分、10美分、5美分和1美分的硬币。在小孩的催促下,售货员想尽快将钱找给小孩。她的做法是:先找不大于67美分的最大硬币25美分硬币,再找不大于67-25=42美分的最大硬币25美分硬币,再找不大于42-25=17美分的最大硬币10美分硬币,再找不大于17-10=7美分的最大硬币5美分硬币,最后售货员再找出两个1美分的硬币。至此,售货员共找给小孩6枚硬币。售货员的原则是拿尽可能少的硬币个数找给小孩。 从另一个角度看,如果售货员将捡出的硬币逐一放在手中,最后一起交给小孩,那么售货员想使自己手中的钱数增加的尽量快些,所以每一次都尽可能地捡面额大的硬币。 装载问题 有一艘大船用来装载货物。假设有n 个货箱,它们的体积相同,重量分别是,货船的最大载重量是c。目标是在船上装更多个数的货箱该怎样装?当然,最简单的作法是“捡重量轻的箱子先往上装”,这是一种贪心的想法。如果用表示装第个货箱,而n w w w ,,21"1=i x i 0=i x 表示不装第i 个货箱,则上述问题是解优化问题: 求,使得 n x x x ,,,21" (4.1.1) ∑=n i i x 1max 满足条件 (4.1.2) 1 w ,0n i i i i x c x =≤=∑,1贪心算法,顾名思义,是在决策中总是作出在当前看来是最好的选择。例如找零钱问题中,售货员每捡一个硬币都想着使自己手中的钱尽快达到需要找钱的总数。在装载问题中,每装一个货箱都想着在不超重的前提下让船装更多的箱子。但是贪心方法并未考虑整体最优解,它所作出的选择只是在某种意义上的局部最优选择。当然,在采用贪心算法时未必不希望结果是整体最优的。事实上,有相当一部分问题,采用贪心算法能够达到整体最优,如前面的找零钱问题以及后面将要讲到的单点源最短路径问题、最小生成树问题、工件排序问题等。为了更好理解贪心算法,我们将装载问题稍加推广,考虑可分割的背包问题。 背包问题 已知容量为M 的背包和件物品。第i 件物品的重量为,价值 n i w

实验4 回溯法

实验4. 回溯法 一、 实验目的 1. 理解回溯法的基本思想。 2. 运用回溯法解决实际问题。 二、 实验环境与地点 1. 实验环境:Windows7,Eclipse 2. 实验地点:网络工程实验室 三、 实验内容与步骤 编写程序完成下列题目,上机调试并运行成功。 1. 有n 个集装箱要装上2艘载重分别为c1和c2 的轮船,其中集装箱 i 的重量为 w i ,且 装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这 2 艘轮船。如果有,找出一种装载方案。 思路: 可以证明,如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。 (1)首先将第一艘轮船尽可能装满; (2)将剩余的集装箱装上第二艘轮船。 将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1。由此可知,装载问题等价于以下特殊的0-1背包问题。 输入: w = [10,40,40] c1 = c2 = 50; 输出:1,2装第一艘船,其余第2艘船。 令第一艘船的装入量为W1,用回溯算法求使得c1?W1达到最小的装载方案;若满足w1+w2+...+wn?W1≤ c2,则回答“Yes ”,否则回答“No ” 步骤: (1) 解空间:子集树 可行性约束函数(选择当前元素): 211c c w n i i +≤∑ =

界限函数(不选择当前元素): 当前载重量cw+剩余集装箱的重量r <=当前最优载重量bestw (2) 算法: public class Loading { // 类数据成员 static int n ;// 集装箱数 static int [] w ; // 集装箱重量数组 static int c ;// 第一艘轮船的载重量 static int cw ; // 当前载重量 static int bestw ;// 当前最优载重量 static int r ;// 剩余集装箱重量 static int [] x ; // 当前解 static int [] bestx ; // 当前最优解 public static int maxLoading(int [] ww , int cc , int [] xx ) { // 初始化类数据成员 n = ww .length - 1; w = ww ; c = cc ; cw = 0; bestw = 0; x = new int [n + 1]; bestx = xx ; // 初始化r for (int i = 1; i <= n ; i ++) r += w [i ]; // 计算最优载重量 backtrack (1); return bestw ; } // 回溯算法 private static void backtrack(int i ) {// 搜索第i 层结点 if (i > n ) {// 到达叶结点 if (cw > bestw ) { for (int j = 1; j <= n ; j ++) bestx [j ] = x [j ]; bestw = cw ; } return ; } 11c x w n i i i ≤∑=

实验四回溯算法

实验四回溯算法的应用 一、实验目的 1.掌握回溯算法的基本思想、技巧和效率分析方法。 2.熟练掌握用回溯算法求解问题的基本步骤,非递归算法框架和递归算法框架。 3.学会利用回溯算法解决实际问题。 二、实验内容 1.问题描述: 题目一、 n后问题 在n*n格的棋盘上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一对角线上,问有多少种摆法。 题目二、数字全排列问题 任意给出从1到N的N个连续的自然数,求出这N个自然数的各种全排列。如N=3时,共有以下6种排列方式:123,132,213,231,312,321。注意:数字不能重复,N由键盘输入。 题目三、0-1 背包问题 有N件物品和一个容量为V的背包。第i件物品的体积是v[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 题目四、连续邮资问题 假设国家发行了n种不同面值的邮票,并且规定每个信封上最多只允许贴m 张邮票。连续邮资问题要求对于给定的n和m的值,给出邮票面值的最佳设计,使得可在1张信封上贴出从邮资1开始,增量为1的最大连续邮资区间。 【输入样例】 n=5

m=4 【输出样例】 1,3,11,15,32 含义:当n=5,m=4时,面值为{1,3,11,15,32}的5种邮票可以贴出邮资的最大连续区间是1到70。 2.数据输入:个人设定,由键盘输入。 3.要求: 1)上述题目任选一做。上机前,完成程序代码的编写 2)独立完成实验及实验报告 三、实验步骤 1.理解算法思想和问题要求; 2.编程实现题目要求; 3.上机输入和调试自己所编的程序; 4.验证分析实验结果; 5.整理出实验报告。

实验报告4.回溯算法

算法设计与分析 实验报告 实验名称_____回溯算法_____ 学院________数学与计算机学院____ 班级_______信科00000___________ 学号_______6666666666__________ 姓名_____000000________________ 2016年月日

{ if(((a+b)==24)||((a-b)==24)||((a*b)==24)||(b!=0&&a%b==0&&a/b==24)){//如果经过上面的计算得到解 while(!route.empty()){ node now=route.front(); printf("%d%c%d=%d\n",now.a,now.oper,now.b,now.sum);//依次输出前面的计算过程 route.pop(); } if((a+b)==24){ if(b>a) swap(a,b); printf("%d+%d=%d\n",a,b,a+b); } if((a-b)==24) printf("%d-%d=%d\n",a,b,a-b); if((a*b)==24) { if(b>a) swap(a,b); printf("%d*%d=%d\n",a,b,a*b); } if(a%b==0&&b!=0&&(a/b)==24) printf("%d/%d=%d\n",a,b,a/b);//a/b比较特殊,要求结果必须是整数 flag=true;//表示找到解,一旦找到任何一个解就退出 } return ; } queue temp=route; node x; x.a=a,x.b=b,x.sum=a+b,x.oper='+'; if(b>a) swap(x.a,x.b); temp.push(x); dfs(cur+1,a+b,num[cur+1],temp);//(((a*b)*c)*d) 模型 temp=route; x.a=a,x.b=b,x.sum=a*b,x.oper='*'; if(b>a) swap(x.a,x.b); temp.push(x); dfs(cur+1,a*b,num[cur+1],temp); temp=route; x.a=a,x.b=b,x.sum=a-b,x.oper='-'; temp.push(x); dfs(cur+1,a-b,num[cur+1],temp);

最佳调度的回溯算法的实验

实验目的: 理解回溯法的原理,掌握调度问题的处理方法,实现最佳调度问题的回溯解决。 问题定义 输入: 1.任务数N 2.机器数M 3.随机序列长度t[i],其中t[i]=x表示第i个任务完成需要时间单位x, 输出: 1.开销时间besttime,表示最佳调度需要时间单位 2.最佳调度序列bestx[],其中bestx[i]=x,表示将第i个任务分配给 第x个机器执行。 实验思想 解空间的表示: 一个深度为N的M叉树。 基本思路:搜索从开始结点(根结点)出发,以DFS搜索整个解空间。 每搜索完一条路径则记录下besttime 和bestx[]序列 开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处向纵深方向移至一个新结点,并成为一个新的活结点,也成为当前扩展结点。 如果在当前的扩展结点处不能再向纵深方向扩展,则当前扩展结点就成为死结点。 此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点;直至找到一个解或全部解。 测试数据及结果 本测试的硬件以及软件环境如下

CPU:PM 1.5G; 内存:768M;操作系统:windows xp sp2;软件平台:JDK1.5;开发环境:eclipse 如图1所示:即为求任务数为10机器数为5的最佳调度的算法结果。 图1 实验结论以及算法分析 通过测试证明算法正确有效。 性能分析的方法:使用JDK 1.5的System.nanoTime(),计算算法消耗的时间,以此来评价算法。(该方法在JDK1.5以下的版本中不支持) 为了不影响算法的准确度,在测试的过程我们注释掉了打印随机字符串的步骤。 由于没有使用限界函数进行优化,算法时间和空间复杂度呈指数级增长。所以该算法不适合较大规模的计算。 图2 图2 蓝线表示机器数一定M=3时,n增大时求解最佳调度对所消耗的时间,该趋势随着指数增加。 图3 图3表示任务数N一定时随着M的增大的增长曲线。 图2和图3表明该程序的时间复杂度与理论分析相符合。 源代码 最佳调度的回溯算法(java描述) BestSchedule.Java package bestSchedule; import ; public class BestSchedule { /** * @author icyfire

回溯算法实验报告

本科学生综合性实验报告 姓名刘春云学号0103918___ 专业软件工程班级_软件103班__ 实验项目名称_n皇后问题的回溯算法实验 指导教师及职称_赵晓平__教授__ 开课学期2011 至_2012 学年_三_学期 上课时间2012 年 2 月20 日

学生实验报告(3) 一、问题描述 n后问题是指在一个n*n的棋盘上放置n个皇后,使得它们彼此不受攻击。而一个皇后可以攻击与它处在同一行或同一列或同一斜线上的任何棋子。故n后问题可以理解为:在一个n*n的棋盘内放置n个皇后,使任意两个皇后不处在同一行或同一列或同一斜线上。 在这个问题中,我用了一个n*n的数组来存储棋盘,由于n后问题的典型是8皇后问题,所以我做的是8皇后问题。得出的解以以下形式出现在文件中:8皇后问题 第1个解为: oxxxxxxx xxxxoxxx xxxxxxxo xxxxxoxx xxoxxxxx xxxxxxox xoxxxxxx xxxoxxxx 二、解题思路 根据条件可以知道皇后肯定是每行都有且只有一个所以我们创建一个数组c[cur]让数组角标表示八皇后的行,用这个角标对应的数组值来确定这个皇后在这行的那一列。 我用递归来做这问题。要求皇后所在的位置必须和其他皇后的位置不在同一行、列和斜线上,所以这个限定条件可以用来判断一个皇后是否能放在当前位置。既然是用递归来解决问题那就要把这个问题分成一个个相同的小问题来实现。 这小问题是什么呢?不难发现我们要在n*n的方格里放好n个皇后那我们就要知道在n(列)*n-1(行)是怎么放的,再有我们事先写好的判断条件放好最后行就搞定了。以此类推我们要知道8*7的怎么方的我们就要知道8*6是怎么样的就好了。所以我们是以一行怎么放作为一个单元,每一行有n个位置可以放,每一个位置我

实验四 回溯法的应用------跳马算法

实验四回溯法的应用------跳马算法 学号:012124345 姓名:梁文耀 一、实验目的 掌握使用回溯法求解问题的基本思路;理解其特点。 二、实验思想 算法的基本思路是: 定义结构体:struct PLACE{int x, int y}表示棋盘上的位置。 依题意,马每跳一步之后都可以从七个不同的方向选择下一步的跳马,当然,前提是跳的这一步在棋盘内且它前面的任何一步都没跳到这一格子上(限界),就可以认为这一步跳成功,否则跳马不成功。若跳马不成功,则找下一个方向尝试跳马,若七个方向都跳马不成功,则回溯。 假设棋盘的行(列)数为n。 在本算法中设置这样一个全局数组:c[8][2]={{2,1},{2,-1},{1,2},{1,-2},{-2,1},{-2,-1},{-1,2},{-1,-2}}; 来记录跳马的八个方向。 三、程序分析(主要算法) int map[12][12], status[12][12], kp; int start,finsh; int c[8][2]={{2,1},{2,-1},{1,2},{1,-2}, {-2,1},{-2,-1},{-1,2},{-1,-2}};

int flag = 0; void prt(int a[][12]) /* 打印棋盘状态*/ { int i,j; printf("\n"); for (i=2;i<=9;i++) { for (j=2;j<=9;j++) printf("%4d",a[i][j]); printf("\n"); } } void status2(void) /* 计算棋盘各点条件数*/ { int i,j,k,i2,j2,kz; for(i=0;i<12;i++) for(j=0;j<12;j++) status[i][j]=100; for(i=2;i<=9;i++) for(j=2;j<=9;j++) { kz=0;

回溯算法(解决着色问题)

实验四回溯算法 一、实验目的 1)理解回溯算法的基本原理,掌握使用回溯算法求解实际问 题。 二、方法原理 回溯法是一种类似穷举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就回退,尝试别的路径。 三、实验设备 PC机一台,C语言、PASCAL语言、Matlab任选 四、掌握要点 搜索到解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯;否则进入该子树,继续按深度优先的策略进行搜索。 五、实验内容 实验内容:(二选一)1)编写程序实现4后问题的求解;2)编写程序实现用3种颜色为图2着色问题;

图2 六、实验要求 1)认真分析题目的条件和要求,复习相关的理论知识,选择适当的解决方案和算法; 2)编写上机实验程序,作好上机前的准备工作; 3)上机调试程序,并试算各种方案,记录计算的结果(包括必要的中间结果); 4)分析和解释计算结果; 5)按照要求书写实验报告; 源代码:着色问题 #i n c l u d e #i n c l u d e #d e f i n e T R U E1 #d e f i n e F A L S E0 #d e f i n e M A X5 #d e f i n e C O L O R C O U N T3

i n t T F(i n t c o l o r,i n t i n d e x,i n t m[][M A X],i n t p[]){ f o r(i n t i=0;i

实验四 回溯法求n皇后问题

本科实验报告 课程名称:算法设计与分析实验项目:回溯法求n皇后问题实验地点: 专业班级:学号:学生姓名: 指导教师:

实验四回溯法求n皇后问题 一、实验目的 1.掌握回溯算法的基本思想 2.通过n皇后问题求解熟悉回溯法 3.使用蒙特卡洛方法分析算法的复杂度 二、实验内容 要求在一个8*8的棋盘上放置8个皇后,使得它们彼此不受“攻击”。两个皇后位于棋盘上的同一行、同一列或同一对角线上,则称它们在互相攻击。现在要找出使得棋盘上8个皇后互不攻击的布局。 三、实验环境 程序设计语言:c++ 编程工具:microsoft visual studio 2010 四、算法描述和程序代码 #include #include using namespace std; int main(){ int queen[8]; int total = 0; //方案计数 int i, j, k; for (i=0;i<8;i++) queen[i] = 0; //八皇后全放在第0列 for (i=1;;){ //首先安放第0行皇后 if(queen[i]<8){ //皇后还可调整 k=0; //检查与第k个皇后是否互相攻击 while(k