第八章-贪心算法

第八章-贪心算法
第八章-贪心算法

第8章贪心算法

8.1简介

8.1.1 例子

例子:有4种硬币,面值分别为2角5分、一角、五分和一分。现在要求以最少的硬币个数找给顾客6角三分。

通常是:先拿两个2角5分的+1个一角+3个一分

这种找法所拿出的硬币个数最少。这种算法其实就是贪心算法。顾名思义:

该算法总是作出在当前看来最好的选择,并且不从整体上考虑最优问题,所作出的选择只是在某种意义上的局部最优解。

上面的解法得到的恰好也是最优解。因此,贪心方法的效率往往是很高的。

假如,面值有一角一分、五分和一分,要找给顾客一角五分。如果还是使用上述贪心算法,得到的解是:一个一角一分+4个一分。而最优解是3个5分。

又例如:

求节点1到节点6的最短路径。用贪心法得19,而实际为17。

显然贪心算法不能对所有问题都能得到最优解,但是对很多问题(包括很多著名的问题)都能产生整体最优解。例如,我们今天要讲的图的单元最短路径问题、最小生成树问题。在有些情况下,算法不能得到整体最优解,但是结果确是最优解的很好近似。

8.1.2 贪心选择性质

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的

选择来达到,即贪心选择来达到。这是贪心算法可行的第一个基本要素.也是贪心算法与动态规划算法的主要区别:

动态规划算法:每步所做出的选样往往依赖于相关子问题的解,因而只有在解出相关子问题后.才能做出选择。

贪心算法:仅在当前状态下做出最好选样,即局部最优选则。然后再去解做出这个选择后产生的相应的子问题。贪心算法所做出的贪心选则可以依赖于以往做过的选则,但决不依赖于将来所做的选样,也不依赖于子问题的解。

动态规划:是自底向上的方法解各子问题;

贪心算法:是自顶向下的方法。每做出一次贪心选择就将所求问题简化为规模更小的子问题.

使用贪心法的难点在于:证明所设计的算法确实能够正确解决所求解的问题。即对于一个具体的问题,必须证明每一步所做出的贪心选择最终导致问题的整体最优解。

首先,考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做出贪心选择后.原问题简化为规模更小的类似子问题。然后,用数学归纳法证明、通过每一步做贪心选择.最终可得到问题的整体最优解。

其中,证明贪心选择后的问题简化为规模最小的类似子问题的关键在于利用该问题的最优子结构性质。

最优子结构性质: 当一个问题的最优解包含其子问题的最优解时,

称此问题具有最优子结构性质。

贪心算法和动态规划算法都要求问题具有最优子结构性质,这是两类算法的一个共同点。但是都具有最优子结构的问题该选则贪心法还是动态规划算法求解?是否能用动态规划法的也能用贪心算法解?

背包问题:

给定n 种物品12{,,,}n u u u 和一个背包,物品i 的体积为i s ,价值为i v 。已经知道背包的承重量为C 。

假设i x 是物体i 被装入背包的部分,10≤≤i x ;要求装满背包且

背包内物体价值最大。

C x

s i

n

i i ≤∑=1

max i n

i i x v ∑=1

选择方法:目标函数的值增加最快,而包载容量的消耗较慢的物体装入包中。故优先选择价值体积比最大的物体装入背包。

背包与0-1背包的区别:

结论0-1背包问题能用动态规划法解,但不能用贪心法解。

8.3单源最短路径问题(狄斯奎诺Dijkstra ’s 算法)

一、问题描述

),(E V G =是一个有向图,每条边上有一个非负整数表示长度值,其中有一

个顶点s 称为源节点。所谓的单源最短路径问题就是:求解该源节点到所有其它节点的最短路径值。不失去一般性,我们假设},...,3,2,1{n V =并且s =1。那么该问题可以使用Dijkstra ’s 算法来求解,该算法是一种贪心算法,并且能求得最优解。

二、算法思想

开始时,我们将所有的顶点划分为两个集合},..,4,3,2{},1{n Y X ==。所有已经计算好的顶点存放在X 中,Y 中表示还没有计算好的。Y 中的每个顶点y 有一个对应的量][y λ,该值是从源顶点到y (并且只经由X 中的顶点)的最短路径值。

(1) 下面就是选择一个][y λ最小顶点Y y ∈,并将其移动到X 中。 (2) 一旦y 被从Y 移动到X 中,Y 中每个和y 相邻的顶点w 的][w λ都要更

新:表示经由y 到w 的一条更短的路径被发现了。

对于任意一个顶点 V v ∈,假如我们使用][v δ表示源顶点到顶点v 的最短路径,最后,我们可以证明上述的贪心法结束后有][][v v λδ=。

三、算法DIJKSTRA

输入:含权有向图G=(V,E), V={1,2,…n} 输出:G 中顶点1到其他顶点的距离

1. }1{←X ;}1{-←V Y ;0]1[=λ

2. For y ←2 to n

If y 相邻于1 then ],1[][y length y ←λ Else ∞=][v λ;

End if

6. end for

7. for j ←1 to n-1

8. 令Y y ∈,找到最小][y λ

9. X ←X ∪{y} /*将y 从Y 移动到X 中 10 Y ←Y-{y}

For 每条边{y,w}

If w ∈Y and ][y λ+length[y,w]< ][w λ then

],[][][w y lenth y w +←λλ /*更新 Y 中和y 相邻顶点的λ值

14. endfor 15.end for

四、举例说明:

(手工解该题目)

813

123456

算法的详细实现:

(1) 有向图用邻接表来表示 如图 (2) 假设每条边是非负的

(3) X 和Y 集合用两个向量来表示X[1..n] ,Y[1..n]。初始时

X[1]=1,Y[1]=0.并且对于2<=i<=n, X[i]=0,Y[i]=1. 因此,执行

}{y X X ?←的操作,

就是X[y]=1, }{y Y Y -←的操作就是,Y[y]=0。

五、证明

下面来证明,使用该DIJKSTRA 方法得到的是最优解,也就是][][y y δλ=。其中,][v δ表示源顶点到顶点v 的最短路径;][y λ是从源顶点到y (并且只经由X 中的顶点)的最短路径值。

证明: 归纳法

(1) 显然0]1[]1[==δλ

(2) 假设,当前将y 移动到X 中,并且在y 之前移动到X 中的任何一个顶

点c ,都有][][c c δλ=。由于][y λ是有限的,也就是说必定存在一条从1到y 路径,长度为][y λ(我们需要来证明][][y y δλ=)。 那么这条路径总可以写作:

π:1→[ ]→[ ]→。。。→[ ]→[ ]→[ ]→y

在上述序列中,我们总是可以找到一个顶点,不妨称之为x

(x X ∈),使得x 之后的顶点均属于Y ,并且x 是在y 前最迟离开Y 的顶点。所以有以下两种情形:

1→[ ]→[ ]→。。。→[ ]→[x ]→y (A) 或是

1→[ ]→[ ]→。。。→[x ]→[ ]…→y (B) √对于情形(A),

[][][,]y x length x y λλ≤+ 算法要求

[](,)x length x y δ=+ 归纳假设

[]y δ= (A)是最短路径

√对于情形(B),

我们将x 之后的顶点不妨称之为w ,即: 1→[ ]→[ ]→。。。→[x ]→[ w]…→y (B)

于是有:

][][w y λλ≤ 由于y 在w 之前离开Y

),(][w x length x +≤λ 算法要求 ),(][w x length x +=δ 归纳假设 ][w δ= 因为π是最短路径 ][y δ≤因为π是最短路径

我们已经说了,][y δ是最短路径了,因此][][y y δλ=。 六、算法分析

O(n 2) 或 O(mn)

8.2.1 稠图的线性时间算法

把算法的复杂度从O(n 2)降到O(m logn).

基本思想是用最小堆数据结构来保持集合Y 中的顶点,使Y 组中离V-Y 最近的顶点y 可以在O(logn)时间内被选出. 算法8.2 SHORTESTPATH

输入:含权有向图G=(V,E), V={1,2,…n}

输出:G 中顶点1到其他顶点的距离.假设已有一个空堆H 1. }1{-←V Y ;0]1[=λ;]1[)1(λ←key

2. For y ←2 to n

If y 相邻于1 then ],1[][y length y ←λ

][)(y y key λ←

INSERT(H,y) Else ∞=][v λ;

][)(y y key λ←

End if

6. end for

7. for j ←1 to n-1

8. Y ←DELETEMIN(H) 10 Y ←Y-{y}

For 对每个邻接于y 的顶点w ∈Y

If ][y λ+length[y,w]< ][w λ then

],[][][w y lenth y w +←λλ

/*更新 Y 中和y 相邻顶点的λ值

][)(w w key λ←

endif

If H w ? then INSERT(H,w) ELSE SIFTUP(H,H -1(w))

endif endfor 15.end for

其中,H -1(w)返回w 再H 中的位置,可以用一个数组实现。

8.3 最小生成树

设G =(V,E)是无向连通带权图,(V,T)是是G 的一个子图,并且T 是一颗树,那么称(V,T)是G 的生成树。如果T 的权之和是所有生成树中最小的,那么则称之为最小生成树。

我们假定G是连通的,如果G是非连通的,那么,可以对G的每个子图应用求解最小生成树的算法。

网络的最小生成树在实际中有广泛应用。例如,在设计通信网络时,用图的顶点表示城市,用边(v,w)的权c[v][w]表示建立城市v和城市w之间的通信线路所需的费用,则最小生成树就给出了建立通信网络的最经济的方案。

8.3.1最小生成树性质

用贪心算法设计策略可以设计出构造最小生成树的有效算法。本节介绍的构造最小生成树的Prim算法和Kruskal算法都可以看作是应用贪心算法设计策略的例子。尽管这2个算法做贪心选择的方式不同,它们都利用了下面的最小生成树性质:

设G=(V,E)是连通带权图,U是V的真子集。如果(u,v)∈E,且u∈U,v∈V-U,且在所有这样的边中,(u,v)的权c[u][v]最小,那么一定存在G的一棵最小生成树,它以(u,v)为其中一条边。这个性质有时也称为MST性质。

8.33 Kruskal算法(克鲁斯卡尔)

一、基本思想

Kruskal算法构造G的最小生成树的基本思想是,首先将G的n个顶点看成n个孤立的连通分支。将所有的边按权从小到大排序。然后从第一条边开始,依边权递增的顺序查看每一条边,并按下述方法连接2个不同的连通分支:当查看到第k条边(v,w)时,如果端点v和w分别是当前2个不同的连通分支T1和T2中的顶点时,就用边(v,w)将T1和T2连接成一个连通分支,然后继续查看第k+1条边;如果端点v和w在当前的同一个连通分支中,就直接再查看第k+1条边。这个过程一直进行到只剩下一个连通分支时为止。

例如,对前面的连通带权图,按Kruskal算法顺序得到的最小生成树上的边如下图所示。

二、KRUSKAL 算法

输入: 具有n 个顶点的带权连通无向图(,)G V E 输出:G 的最小生成树T

1. 以非降序的方式对E 中各条边的权进行排序

2. for each v V ∈

3. MAKESET({}v );

4. end for

5. {}T =

6. while 1T n <-

7. let (,)x y 为E 中的下一条边 8. if ()()FND x FND y ≠ then 9. (,)Add x y to T 10. (,)UNION x y

11. end if 12.end while

关于集合的一些基本运算可用于实现Kruskal 算法。

按权的递增顺序查看等价于对优先队列执行removeMin 运算。可以用堆实

现这个优先队列。

对一个由连通分支组成的集合不断进行修改,需要用到抽象数据类型并查集UnionFind 所支持的基本运算。

三、Kruskal 算法的正确性

证明:我们只要证明,使用Kruskal 算法过程中,每次循环所得到的T (从空集增至最小生成树)总是图G 的最小生成树的子集即可。使用归纳法+反证法。

(1)G 总是具有一个最小生成树,不妨记为*T 。 (2)当前要加入的边为(,)e x y =。

(3)包含x 的那颗子树的所有顶点用X 表示。

(4)假设在(,)e x y =加入之前得到的T 均满足*T T ?,其中

,x X y V X ∈∈-。

令'{}T T e =?,下面我们要证明'T 也是图G 的最小生成树的子集。 依据归纳假设,有*T T ?。 (A)如果*e T ∈:显然有'*T T ?

(B)如果*e T ?:那么*{}T e ?必将构成一个环,也就是*T 不再是树。我们知道*T 中必定包含这样一条边'(,)e w z =,且,w X z V X ∈∈-,且cost('e )≥cost(e )。否则,'e 将被选择加入。 下面我们来证明'e 就是e 。

定义***'{}{}T T e e =-?,那么**T 也是图的一个生成树,并且cost(**T )

证明完毕。

四、时间复杂度:

当图的边数为e时,Kruskal算法所需的计算时间是(log)

O e e。

8.4 Prim算法(普里姆)

一、基本思想

设G=(V,E)是连通带权图,V={1,2,…,n},。构造G的最小生成树.

Prim算法的基本思想:

首先置S={1},然后,只要S是V的真子集,就作如下的贪心选择:选取满足条件i∈S,j∈V-S,且c[i][j]最小的边,将顶点j添加到S中。这个过程一直进行到S=V时为止。

在这个过程中选取到的所有边恰好构成G的一棵最小生成树。

利用最小生成树性质和数学归纳法容易证明,上述算法中的边集合T始终包含G的某棵最小生成树中的边。因此,在算法结束时,T中的所有边构成G 的一棵最小生成树。

例如,对于右图中的带权图,按Prim算法选取边的过程如下页图所示

二、算法

算法8.4 PRIM

输入:含权有向图G=(V,E), V={1,2,…n}

输出:由G 生成的最小耗费生成树T 组成的边的集合 1.T ←{};X ←{1};Y ←V-{1} 2. For y ←2 to n

If y 相邻于1 then N[y]←1

C[y] ←c[1,y]

Else ∞=][y C ;

End if

8. end for

9. for j ←1 to n-1 {寻找n-1条边} 10. 令Y y ∈,找到最小][y C

11. T ←T ∪{(y,N[y]} {将边y ,N[y]加入T} 12. X ←X ∪{y} /*将y 从Y 移动到X 中 13 Y ←Y ∪{y}

For 每个相邻于y 的顶点w ∈Y If c[y,w]

C[w] ←c[y,w]

18. end if 19. endfor 20.end for

在上述Prim 算法中,还应当考虑如何有效地找出满足条件i ∈S,j ∈V-S ,且权c[i][j]最小的边(i,j)。

三、算法分析

用这个办法实现的Prim 算法所需的计算时间为2()O n

当图的边数为e 时,Kruskal 算法所需的计算时间是(log )O e e 。当2()e n =Ω时,

Kruskal算法比Prim算法差,但当2

e o n

时,Kruskal算法却比Prim算法好

()

得多。

8.6 哈夫曼编码

哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。

哈夫曼编码思想:给出现频率高的字符较短的编码,出现频率较低的字符以较长的编码,可以大大缩短总码长。

前缀码

对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。这种编码称为前缀码。

例:a:10, b:101存在二义性

编码的前缀性质可以使译码方法非常简单。

表示最优前缀码的二叉树总是一棵完全二叉树,即树中任一结点都有2个儿子结点。

平均码长定义为:使平均码长达到最小的前缀码编码方案称为给定编码字符集C的最优前缀码。构造哈夫曼编码

哈夫曼提出构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼编码。

哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。

算法以|C|个叶结点开始,执行|C|-1次的“合并”运算后产生最终所要求的树T。

在书上给出的算法huffmanTree中,编码字符集中每一字符c的频率是f(c)。以f为键值的优先队列Q用在贪心选择时有效地确定算法当前要合并的2棵具有最小频率的树。一旦2棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的2棵树的频率之和,并将新树插入优先队列Q。经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。

算法8.6 HUFFMAN

输入:n个字符的集合C 和他们的频度

输出:Cde huffman树(V,T)

1.根据频度将所有字符插入最小堆H

2.V←C;T={}

3.For j←1 to n-1

4. c←DELETEMIN(H)

5.'C←DELETEMIN(H)

6. f(v) ←f(c)+f(c') {v是一个新结点}

7. INSERT(H,v)

8. V=V∪{v} {添加v到V}

9. T=T∪{(v,c),(v, c')}{使c'和c成为T中v的孩子}

10. End for

时间复杂度:

算法huffmanTree用最小堆实现优先队列Q。初始化优先队列需要O(n)计算时间,由于最小堆的取最小和put运算均需O(logn)时间,n-1次的合并总共需要O(nlogn)计算时间。因此,关于n个字符的哈夫曼算法的计算时间为O(nlogn)

哈夫曼算法的正确性

要证明哈夫曼算法的正确性,只要证明最优前缀码问题具有贪心选择性质和最优子结构性质。

(1)贪心选择性质

(2)最优子结构性质

算法实验 递归回溯解八皇后问题

深圳大学实验报告 课程名称:算法分析与复杂性理论 实验项目名称:八皇后问题 学院:计算机与软件学院 专业:软件工程 指导教师:杨烜 报告人:学号:班级:15级软工学术型实验时间:2015-12-08 实验报告提交时间:2015-12-09 教务部制

一.实验目的 1.掌握选回溯法设计思想。 2.掌握八皇后问题的回溯法解法。 二.实验步骤与结果 实验总体思路: 根据实验要求,通过switch选择八皇后求解模块以及测试数据模块操作,其中八皇后模块调用摆放皇后函数模块,摆放皇后模块中调用判断模块。测试数据模块主要调用判断模块进行判断,完成测试。用一维数组保存每行摆放皇后的位置,根据回溯法的思想递归讨论该行的列位置上能否放置皇后,由判断函数Judge()判断,若不能放置则检查该行下一个位置。相应结果和过程如下所示(代码和结果如下图所示)。 回溯法的实现及实验结果: 1、判断函数 代码1: procedure BTrack_Queen(n) //如果一个皇后能放在第K行和X(k)列,则返回true,否则返回false。 global X(1:k);integer i,k i←1 while i0 do X(k)←X(k)+1 //移到下一个位置 while X(k)<=n and not Judge(k) do //判断能否放置皇后 X(k)←X(k)+1 repeat if X(k)<=n //找到一个位置 then if k=n //是一个完整的解吗

0028算法笔记——【回溯法】批作业调度问题和符号三角形问题

1、批作业调度问题 (1)问题描述 给定n个作业的集合{J1,J2,…,Jn}。每个作业必须先由机器1处理,然后由机器2处理。作业Ji需要机器j的处理时间为tji。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。所有作业在机器2上完成处理的时间和称为该作业调度的完成时间和。 批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。 例:设n=3,考虑以下实例: 这3个作业的6种可能的调度方案是1,2,3;1,3,2;2,1,3; 2,3,1;3,1,2;3,2,1;它们所相应的完成时间和分别是19,18,20,21,19,19。易见,最佳调度方案是1,3,2,其完成时间和为18。 (2)算法设计

批处理作业调度问题要从n个作业的所有排列中找出具有最小完成时间和的作业调度,所以如图,批处理作业调度问题的解空间是一颗排列树。按照回溯法搜索排列树的算法框架,设开始时x=[1,2,……n]是所给的n个作业,则相应的排列树由x[1:n]的所有排列构成。 算法具体代码如下: [cpp]view plain copy 1.#include "stdafx.h" 2.#include https://www.360docs.net/doc/c017805256.html,ing namespace std; 4. 5.class Flowshop 6.{ 7.friend int Flow(int **M,int n,int bestx[]); 8.private: 9.void Backtrack(int i); 10. 11.int **M, // 各作业所需的处理时间

12. *x, // 当前作业调度 13. *bestx, // 当前最优作业调度 14. 15. *f2, // 机器2完成处理时间 16. f1, // 机器1完成处理时间 17. f, // 完成时间和 18. 19. bestf, // 当前最优值 20. n; // 作业数 21. }; 22. 23.int Flow(int **M,int n,int bestx[]); 24. 25.template 26.inline void S &a, Type &b); 27. 28.int main() 29.{ 30.int n=3,bf; 31.int M1[4][3]={{0,0,0},{0,2,1},{0,3,1},{0,2,3}}; 32. 33.int **M=new int*[n+1]; 34. 35.for(int i=0;i<=n;i++) 36. { 37. M[i]=new int[3]; 38. } 39. cout<<"M(i,j)值如下:"<

第8章怎样研究算法排序算法示例练习题答案解析

第8章怎样研究算法:排序算法示例 1、排序算法是最基本的算法,很多复杂算法都是以排序为基础进行构造的。关于排序算法,下列说法不正确的是_____。 (A)大规模数据集合中查找有无某些元素的问题,有序数据集合比无序数据集合的查找要快得多; (B)大规模数据集合中按元素分组进行计算的问题,有序数据集合比无序数据集合的计算要快得多; (C)对无序数据集合,两个算法X和Y:X采用无序数据处理,Y采用先将无序数据排序成有序数据,然后进行处理;则对前述(A)、(B)两类问题,Y算法一定比X算法慢; (D)上述说法有不正确的; 答案:C 解释: 本题考核排序算法的研究 在大规模数据集合中查找,有序数据集合有利算法进行和判断,要比无序数据集合查找的快,对于(C)选项,Y算法尽管需要排序后再处理,但排序处理后的数据查找更加快捷,因此可能Y算法比X算法更快。 具体内容请参考排序算法以及第八章课件。 2、下列三个算法是关于“大规模数据集合中查找有无某些元素”问题的算法:针对一个“学生”数据表,如下示意,找出“成绩”为某一分数的所有学生。 【算法A1】 Start of algorithm A1 Step 1. 从数据表的第1条记录开始,直到其最后一条记录为止,读取每一条记录,做Step 2。Step 2. 对每一条记录,判断成绩是否等于给定的分数:如果是,则输出;如果不是,则不输出。

End of algorithm A1 【算法A2】 Start of algorithm A2 Step 1. 从数据表的第1条记录开始,直到其最后一条记录为止,读取每一条记录,做Step 2和Step 3。 Step 2. 对每一条记录,判断成绩是否等于给定的分数:如果等于,则输出;如果不等于,则不输出。 Step 3. 判断该条记录的成绩是否小于给定的分数:如果不是,则继续;否则,退出循环,算法结束。 End of algorithm A2 【算法A3】 Start of algorithm A3 Step 1. 假设数据表的最大记录数是n,待查询区间的起始记录位置Start为1,终止记录位置Finish为n; Step 2. 计算中间记录位置I = (Start+Finish)/2,读取第I条记录。 Step 3. 判断第I条记录的成绩与给定查找分数: (3.1)如果是小于关系,则调整Finish = I-1;如果Start >Finish则结束,否则继续做Step 2; (3.2)如果是大于关系,则调整Start = I+1;如果Start>Finish则结束,否则继续做Step 2; (3.3)如果是等于关系,则输出,继续读取I周围所有的成绩与给定查找条件相等的记录并输出,直到所有相等记录查询输出完毕则算法结束。 End of algorithm A3 针对上述三个算法,回答下列问题: (1)关于算法A1, A2, A3的快慢问题,下列说法正确的是_____。 (A)算法A1快于算法A2,算法A2快于算法A3; (B)算法A2快于算法A1,算法A2快于算法A3; (C)算法A3快于算法A2,算法A2快于算法A1; (D)算法A1快于算法A3,算法A3快于算法A2; (E)上述都不正确。 答案:C 解释: 本题考核排序算法的研究 首先,数据是有序排列的,从大到小。 算法A1依次搜索,穷举。 算法A2与A1一样,穷举,不同的是它利用数据是从大到小排序的特点,因此,如果当前数据比如果小于目标数,那么说明只有的也一定小于,则目标不在序列中。因此,A2比A1快。 算法A3利用数据有序特点,采用二分查找,每次将目标数与中间值比较,缩小搜索范围,因此A3比A2快。 综上,答案选(C)。 具体内容请参考排序算法以及第八章课件。

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

计算机与信息科学学院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

第四章贪心算法

第四章贪心算法 一、课本+作业 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 。

回溯算法的一些例题

回溯算法 搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。如迷宫问题:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其它方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路可走,则返回一步,再看其它方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断搜索回溯再搜索,直到找到新的出路或从原路返回入口处无解为止。 递归回溯法算法框架[一] procedure Try(k:integer); begin for i:=1 to 算符种数 Do if 满足条件 then begin 保存结果 if 到目的地 then 输出解 else Try(k+1); 恢复:保存结果之前的状态{回溯一步} end; end; 递归回溯法算法框架[二] procedure Try(k:integer); begin if 到目的地 then 输出解 else for i:=1 to 算符种数 Do if 满足条件 then begin 保存结果 Try(k+1); end; end;

例 1:素数环:把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。【算法分析】非常明显,这是一道回溯的题目。从1 开始,每个空位有 20(19)种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第 20个数还要判断和第1个数的和是否素数。 〖算法流程〗1、数据初始化; 2、递归填数: 判断第J种可能是否合法; A、如果合法:填数;判断是否到达目标(20个已填完):是,打印结果;不是,递归填下一个; B、如果不合法:选择下一种可能; 【参考程序】 program z74;框架[一] var a:array[0..20]of byte; b:array[0..20]of boolean; total:integer; function pd(x,y:byte):boolean; var k,i:byte; begin k:=2; i:=x+y; pd:=false; while (k<=trunc(sqrt(i)))and(i mod k<>0) do inc(k); if k>trunc(sqrt(i)) then pd:=true; end; procedure print; var j:byte; begin inc(total);write('<',total,'>:'); for j:=1 to 20 do write(a[j],' '); writeln; end; procedure try(t:byte); var i:byte; begin for i:=1 to 20 do if pd(a[t-1],i)and b[i] then begin a[t]:=i; b[i]:=false; if t=20 then begin if pd(a[20],a[1]) then print;end

第八章-贪心算法

第8章贪心算法 8.1简介 8.1.1 例子 例子:有4种硬币,面值分别为2角5分、一角、五分和一分。现在要求以最少的硬币个数找给顾客6角三分。 通常是:先拿两个2角5分的+1个一角+3个一分 这种找法所拿出的硬币个数最少。这种算法其实就是贪心算法。顾名思义: 该算法总是作出在当前看来最好的选择,并且不从整体上考虑最优问题,所作出的选择只是在某种意义上的局部最优解。 上面的解法得到的恰好也是最优解。因此,贪心方法的效率往往是很高的。 假如,面值有一角一分、五分和一分,要找给顾客一角五分。如果还是使用上述贪心算法,得到的解是:一个一角一分+4个一分。而最优解是3个5分。 又例如: 求节点1到节点6的最短路径。用贪心法得19,而实际为17。 显然贪心算法不能对所有问题都能得到最优解,但是对很多问题(包括很多著名的问题)都能产生整体最优解。例如,我们今天要讲的图的单元最短路径问题、最小生成树问题。在有些情况下,算法不能得到整体最优解,但是结果确是最优解的很好近似。 8.1.2 贪心选择性质 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的

选择来达到,即贪心选择来达到。这是贪心算法可行的第一个基本要素.也是贪心算法与动态规划算法的主要区别: 动态规划算法:每步所做出的选样往往依赖于相关子问题的解,因而只有在解出相关子问题后.才能做出选择。 贪心算法:仅在当前状态下做出最好选样,即局部最优选则。然后再去解做出这个选择后产生的相应的子问题。贪心算法所做出的贪心选则可以依赖于以往做过的选则,但决不依赖于将来所做的选样,也不依赖于子问题的解。 动态规划:是自底向上的方法解各子问题; 贪心算法:是自顶向下的方法。每做出一次贪心选择就将所求问题简化为规模更小的子问题. 使用贪心法的难点在于:证明所设计的算法确实能够正确解决所求解的问题。即对于一个具体的问题,必须证明每一步所做出的贪心选择最终导致问题的整体最优解。 首先,考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做出贪心选择后.原问题简化为规模更小的类似子问题。然后,用数学归纳法证明、通过每一步做贪心选择.最终可得到问题的整体最优解。 其中,证明贪心选择后的问题简化为规模最小的类似子问题的关键在于利用该问题的最优子结构性质。 最优子结构性质: 当一个问题的最优解包含其子问题的最优解时, 称此问题具有最优子结构性质。 贪心算法和动态规划算法都要求问题具有最优子结构性质,这是两类算法的一个共同点。但是都具有最优子结构的问题该选则贪心法还是动态规划算法求解?是否能用动态规划法的也能用贪心算法解? 背包问题: 给定n 种物品12{,,,}n u u u 和一个背包,物品i 的体积为i s ,价值为i v 。已经知道背包的承重量为C 。

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

第四章作业 部分参考答案 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

算法习题回溯法

算法设计与分析第三次作业 计科三班康玥20110801330 5-3 设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wi,j是从供应商j处购得的部件i的重量,ci,j是相应的价格。试设计一个算法,给出总价格不超过c的最小重量机器设计。 Input 由文件input.txt给出输入数据。每组测试数据第一行有3 个正整数n,m和d。接下来的2n行,每行m个数。前n行是ci,j,后n行是wi,j。 Output 将计算的最小重量及每个部件的供应商输出到文件output.txt Sample Input 3 3 4 1 2 3 3 2 1 2 2 2 1 2 3 3 2 1 2 2 2 Sample Output 4 1 3 1 #include #include #include #define N 1000 using namespace std; int n,m,d,cp=0,cw=0,sum=0; int c[N][N],w[N][N]; void backtrack(int i){ if(i>n){ if(cw

cp-=c[i][j]; } } int main(){ ifstream fin("input.txt",ios::in); fin>>n>>m>>d; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) fin>>c[i][j]; sum+=c[i][1]; } for(int k=1;k<=n;k++) for(int j=1;j<=m;j++) fin>>w[k][j]; backtrack(1); ofstream fout("output.txt",ios::out); cout< #include

贪心算法设计及其实际应用研究

哈尔滨师范大学 学年论文 题目关于贪心算法研究 学生*** 指导教师 年级2009级 专业计算机科学与技术 系别计算机科学与技术 学院计算机科学与信息工程学院 哈尔滨师范大学 年月

论文提要 为满足人们对大数据量信息处理的渴望,解决各种实际问题,计算机算法学得到了飞速的发展。设计一个好的求解算法更像是一门艺术而不像是技术。 当一个问题具有最优子结构性质和贪心选择性质时,贪心算法通常会给出一个简单、直观、高效的解法。贪心算法通过一系列的选择来得到一个问题的解。它所作的每一个选择都是在当前状态下具有某种意义的最好选择,即贪心选择;并且每次贪心选择都能将问题化简为一个更小的与原问题具有相同形式的子问题。尽管贪心算法对许多问题不能总是产生整体最优解,但对诸如最短路径问题、最小生成树问题,以及哈夫曼编码问题等具有最优子结构和贪心选择性质的问题却可以获得整体最优解。而且所给出的算法一般比动态规划算法更加简单、直观和高效。

贪心算法设计及其实际应用研究 *** 摘要:在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。贪心算法所作的选择可以依赖于以往所作过的选择,但决不依赖于将来的选择,也不依赖于子问题的解,因此贪心算法与其它算法相比具有一定的速度优势。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。本文讲述了贪心算法的含义、基本思路及实现过程,贪心算法的核心、基本性质、特点及其存在的问题。并通过贪心算法的特点举例列出了以往研究过的几个经典问题,对于实际应用中的问题,也希望通过贪心算法的特点来解决。 关键词:贪心算法;哈夫曼编码;最小生成树;多处最优服务次序问题;删数问题 一、贪心算法的基本知识概述 (一)贪心算法的核心 贪心算法的核心问题是选择能产生问题最优解的最优度量标准,即具体的贪心策略。贪心策略是指从问题的初始状态出发,通过若干次的贪心选择而得出最优值(或较优解)的一种解题方法。其实,从“贪心策略”一词我们便可以看出,贪心策略总是做出在当前看来是最优的选择,也就是说贪心策略并不是从整体上加以考虑,它所做出的选择只是在某种意义上的局部最优解,而许多问题自身的特性决定了该题运用贪心策略可以得到最优解或较优解。 (二)贪心算法的理论基础 正如前文所说的那样,贪心策略是最接近人类认知思维的一种解题策略。但是,越是显而易见的方法往往越难以证明。下面我们就来介绍贪心策略的理论—拟阵。 “拟阵”理论是一种能够确定贪心策略何时能够产生最优解的理论,虽然这套理论还很不完善,但在求解最优化问题时发挥着越来越重要的作用。 拟阵M定义为满足下面3个条件的有序对(S,I): (1)S是非空有限集; (2)I是S的一类具有遗传性质的独立子集族,即若B∈I,则B是S的独立子集,且B的任意子集也都是S的独立子集。空集¢必为I的成员; (3)I满足交换性质,即若A∈I,B∈I且|A|<|B|,则存在某一元素x∈B-A,使得A∪{x}∈I。 定理1.1 拟阵M中所有极大独立子集具有相同大小。 引理1.1 (拟阵的贪心选择性质)设M=(S,I)是具有权函数M的带权拟阵,且S 中元素依权值从大到小排列,又设x∈S是S中第一个使得{x}是独立子集元素,则存在S 的最优子集A使得x∈A。 引理1.2 设M=(S,I)是拟阵。若S中元素x不是空集¢的一个可扩元素,则x也不可能是S中任一独立子集A的可扩展元素。 引理1.3 (拟阵的最优子结构性质)设x是求带权拟阵M=(S,I)的最优子集的贪

算法导论 第八章答案

8.2-4 :在O(1)的时间内,回答出输入的整数中有多少个落在区间[a...b]内。给出的算法的预处理时间为O(n+k) 算法思想:利用计数排序,由于在计数排序中有一个存储数值个数的临时存储区C[0...k],利用这个数组即可。 #include using namespace std; //通过改编计数排序而来,因为有些部分需要注释掉 void counting_sort(int*&a, int length, int k, int*&b, int*&c); int main() { const int LEN =100; int*a =newint[LEN]; for(int i =0; i < LEN; i++) a[i] = (i -50)*(i -50) +4; int* b =new int[LEN]; const int k =2504; int* c =new int[k +1]; counting_sort(a, LEN, k, b, c); //这里需要注释掉 //for(int i = 0; i < LEN; i++) //cout<>m>>n) { if(m >n) cout<<"区间输入不对"< k && m >0) cout<<"个数为"< k && m <=0) cout<<"个数为"<= 0; i--) { b[c[a[i]] - 1] = a[i]; c[a[i]]--; }*/ } PS:计数排序的总时间为O(k+n),在实践中,如果当k = O(n)时,我们常常采用计数排序,

计算机科学导论-致远学院-上海交通大学

上海交通大学致远学院2015年秋季学期 《计算机科学导论》课程教学说明 一.课程基本信息 1.开课学院(系):致远学院 2.课程名称:《计算机科学导论》(Introduction to Computer Science) 3.学时/学分:48学时/ 3学分 4.先修课程:无 5.上课时间:第1周-第16周;星期二第6节-第8节 6.上课地点:上院200室 7.任课教师:高晓沨(gao-xf@https://www.360docs.net/doc/c017805256.html,) 8.办公室及电话:电信群楼3号楼328室(34207407) 9.助教:朱旭东(nongeek.zv@https://www.360docs.net/doc/c017805256.html,)和吴双(steinsgate@https://www.360docs.net/doc/c017805256.html,) 10.Office hour:周五下午14:00-16:00,电信群楼3-328室 二.课程主要内容(中英文) 第一章计算机科学概论(Overview of Computer Science) 主要内容:概述计算机科学发展历史,了解现代计算机的发展和应用领域,掌握计算机的特点,介绍计算机科学主要学科与课程内容。 重点与难点:突出介绍计算机科学的起源与发展,强调计算机科学对技术的影响,阐述课程主要目标。 第二章集合论,函数,关系(Set, Function, and Relation) 主要内容:熟悉集合,函数,关系等基本概念及基本定理,并了解它们在计算机科学中的作用。 重点与难点:集合悖论,关系演算,函数中的五个公理。 第三章基数/势(Cardinality) 主要内容:学习基数及其中的基本概念,掌握与之相关的重要原理,并了解它们在计算机科学中的作用。 重点与难点:自然数,等势,有限集/无限集,鸽巢原理等。 第四章证明(Proof) 主要内容:了解基本证明技巧,包括一般论述法、逆推法、反证法、数学归纳法等。 重点与难点:理解皮亚诺公理与数学归纳法适用范围,学会一般证明方法。 第五章逻辑(Logic) 主要内容:掌握命题逻辑、谓词逻辑中的相关概念,介绍数理逻辑的发展以及其和计算

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

算法设计与分析基础第八章作业

第八章 习题8.1 1.a.动态规划和分治法有什么共同特点? b.这两种技术之间有什么主要的不同点? 解: a.动态规划和分治法都是将问题的实例划分为若干个小的实例。 b.动态规划中的子问题是有交叠的,子问题中重复的部分只要计算一次,避免了许多问题重复计算;而分治法的子问题是独立的,子问题中即使有重复的部分也会计算多次。 3.书中在研究计算C(n,k)的动态规划算法的时间效率时,做出了如下的断言,请证明之。 k?1k 2 +k(n?k)∈Θ(nk) 解: k?1k +k n?k=nk?1 k2? 1 k 对0≤k≤n,有k2≤nk≤n2,则 nk?1 k2? 1 k≤nk? 1 nk? 1 k≤nk 所以在研究计算C(n,k)的动态规划算法的时间效率时,认定: k?1k +k(k?n)∈Θ(nk)

1.对由下面邻接矩阵定义的有向图,应用Warshall 算法求它的传递闭包。 1000010000 00100 解: R (0)=R (1)=R (2)=R (3)=R (4)= 001100000100 所以题中矩阵的传递闭包为R (4)= 0 1001111000 00100 。 习题8.4 4.a.判断正误:背包问题实例的动态规划表中某一行值的序列总是非递减的。 b.判断正误:背包问题实例的动态规划表中某一列值的序列总是非

解: a.正确。V[i,j]能够放进承重量为j的背包中的前i个物品的中最有价值的子集的总价值。V[i,j+1]表示背包的承重量增加了,从前i个物品中选出最优价值的子集的总价值,此时背包的总价值只可能增加或者不变,而不会减少。可知V[i,j+1] ≥V[i,j]恒成立。所以在动态规划表中某一行值得序列总是非递减的。 b. 正确。由定义8.12和8.13可知,v[0,j]=0,v[i,0]=0; 当i,j>0时,V[i,j]=max{V[i-1,j],v i+ V[i-1,j-w i]} 即V[i,j]≥V[i-1,j]≥0恒成立。所以在动态规划表中某一列值得序列总是非递减的。

最优化理论与算法第八章

第八章 约束优化最优性条件 §8.1 约束优化问题 一、 问题基本形式 min ()f x 1()0 1,,.. ()0 ,,i e i e c x i m s t c x i m m +==?? ≥=? (8.1) 特别地,当()f x 为二次函数,而约束是线性约束时,称为二次规划。 记 { }1()0 (1, ,);()0 , ,i e i e X x c x i m c x i m m +===≥=,称之为可行域(约束域) 。 {}1, ,e E m =,{}1, ,e I m m +=,{}()()0 i I x i c x i I ==∈ 称()E I x 是在x X ∈处的积极约束的指标集。 积极约束也称有效约束,起作用约束或紧约束(active constraints or binding constraints )。 应该指出的是,如果x * 是(1)的局部最优解,且有某个0i I ∈,使得 0()0i c x *> 则将此约束去掉,x * 仍是余下问题的局部最优解。 事实上,若x *不是去掉此约束后所得问题的局部极小点,则意味着0δ?>,存在x δ,使得 x x δδ*-<,且()()f x f x δ*<,这里x δ满足新问题的全部约束。注意到当δ充分小时,由0() i c x 的连续性,必有0()0i c x δ≥,由此知x δ是原问题的可行解,但()()f x f x δ*<,这与x * 是局部极小 点矛盾。 因此如果有某种方式,可以知道在最优解x * 处的积极约束指标集()()A x E I x **=,则问题 可转化为等式的约束问题: min ()f x .. ()0i s t c x = ()i A x *∈ (8.2) 一般地,这个问题较原问题(8.1)要简单,但遗憾的是,我们无法预先知道()A x * 。

算法设计与分析--回溯法

回溯算法的应用 课程名称:算法设计与分析院系: 学生姓名: 学号: 专业班级: 指导教师: 2013年12月27日

回溯算法的应用 摘要:回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。 回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有可行的子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这就是以深度优先的方式系统地搜索问题解的回溯算法,它适用于解决一些类似n 皇后问题等求解方案问题,也可以解决一些最优化问题。 在做题时,有时会遇到这样一类题目,它的问题可以分解,但是又不能得出明确的动态规划或是递归解法,此时可以考虑用回溯法解决此类问题。回溯法的优点在于其程序结构明确,可读性强,易于理解,而且通过对问题的分析可以大大提高运行效率。关键词:回溯法深度优先搜索递归

目录 第1章绪论 (1) 1.1 回溯算法的背景知识 (1) 1.2 回溯法的前景意义 (1) 第2章回溯算法的理论知识 (2) 2.1 回溯算法设计过程 (2) 2.2 回溯算法框架 (2) 2.3 回溯算法的一般性描述 (4) 第3章找n个数中r个数的组合问题 (5) 3.1 问题描述 (5) 3.2 问题分析 (5) 3.3 算法设计 (5) 3.4 测试结果与分析 (6) 第4章流水作业车间调度问题 (8) 4.1 问题描述 (8) 4.2 问题分析 (8) 4.3 算法设计 (8) 4.4 测试结果与分析 (10) 第5章结论 (11) 参考文献 (12)

第四章算法作业

骆吉洲作业: 1. 设有n种不同面值的硬币,个个硬币的面值存于数组T[1:n]中。现在用这些硬币来找钱。各种硬币使用的各数不限。 (1)当只用面值为T[1]、T[2],…,T[i]来找出钱j时,所用的硬币的最小个数记为C(i,j),写出C(i,j)的递推式。 (2)设计一个动态规划算法以计算C(n,j),1≤j≤L,并且只使用一个规模为L的数组,并分析该算法的复杂度。 (3)设C(n,j),1≤j≤L已经计算出来,对任意钱数m(小于等于L),确定用最少硬币数找出钱m的策略。证明该问题有贪心选择性,设计解该问题的贪心算法,并分析其复杂度。 答: (1)递推式: C(i,j)={ 0 j=0 j/T[1] j>0且i=1 min 1≤k≤j/T[i] {k+C(i?1,j?k×T[i])} j>0且i≠1 (2)算法设计:根据(1)中的递推公式,计算C(i,j)时只可能会用到C(i-1,x),其中x的取值区间为[1,j-1]。不会使用x>j的元素数值。假设一个n×L阶矩阵,只需要从左往右计算,每列从上往下计算C(i,j),并使用一个规模为L的数组即可。 算法伪代码: Input:硬币面值数组T[1:n],待找钱数L Output:使用硬币的最小个数x的数组 GET-CHANGE(T,L)

1 n←length(T) 2 create array x[1:L] 3 for j←1 to L 4 d o x[j]←j/T[1] 5 for i←2 to n 6 do for j←L to 1 7 do for k←1 to j/T[i] 8 do if x[j-k*x]+k

相关文档
最新文档