8、某个问题的最优解包含着其子问题的最优解。
这种性质称为最优子结构性质。
9、回溯法的基本思想是在一棵含有问题全部可能解的状态空间树上进行深度优先搜索,解为叶子结点。
搜索过程中,每到达一个结点时,则判断该结点为根的子树是否含有问题的解,如果可以确定该子树中不含有问题的解,则放弃对该子树的搜索,退回到上层父结点,继续下一步深度优先搜索过程。
在回溯法中,并不是先构造出整棵状态空间树,再进行搜索,而是在搜索过程,逐步构造出状态空间树,即边搜索,边构造。
10、P(Polynomial问题):
也即是多项式复杂程度的问题。
NP就是Non-deterministic Polynomial的问题,也即是多项式复杂程度的非确定性问题。
NPC(NPComplete)问题,这种问题只有把解域里面的所有可能都穷举了之后才能得出答案,这样的问题是NP里面最难的问题,这种问题就是NPC问题。
1.备忘录方法和动态规划算法相比有何异同?
简述之。
备忘录方法是动态规划算法的变形。
与动态规划算法一样,备忘录方法用表格保存已解决的子问题的答案,在下次需要解此问题时,只要简单地查看该子问题的解答,而不必重新计算。
备忘录方法与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。
因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同的子问题的重复求解,而直接递归方法没有此功能。
2.简述回溯法解题的主要步骤。
回溯法解题的主要步骤包括:
1)针对所给问题,定义问题的解空间;
2)确定易于搜索的解空间结构;
3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
3.简述动态规划算法求解的基本要素。
动态规划算法求解的基本要素包括:
1)最优子结构是问题能用动态规划算法求解的前提;
2)动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果,即重叠子问题。
4.简述回溯法的基本思想。
回溯法的基本做法是搜索,在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。
如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
5.简要分析在递归算法中消除递归调用,将递归算法转化为非递归算法的方法。
将递归算法转化为非递归算法的方法主要有:
1)采用一个用户定义的栈来模拟系统的递归调用工作栈。
该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。
2)用递推来实现递归函数。
3)通过Cooper变换、反演变换能将一些递归转化为尾递归,从而迭代求出结果。
后两种方法在时空复杂度上均有较大改善,但其适用范围有限。
6.简要分析分支限界法与回溯法的异同。
1)求解目标:
回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
2)搜索方式的不同:
回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
7.简述算法复杂性的概念,算法复杂性度量主要指哪两个方面?
算法复杂性是算法运行所需要的计算机资源的量,需要时间资源的量称为时间复杂性,需要的空间资源的量称为空间复杂性。
这个量应该只依赖于算法要解的问题的规模、算法的输入和算法本身的函数。
如果分别用N、I和A表示算法要解问题的规模、算法的输入和算法本身,而且用C表示复杂性,那么,应该有C=F(N,I,A)。
算法复杂性度量主要包括算法的时间复杂性和算法的空间复杂性。
8.贪心算法求解的问题主要具有哪些性质?
简述之。
贪心算法求解的问题一般具有二个重要的性质:
一是贪心选择性质,这是贪心算法可行的第一个基本要素;
另一个是最优子结构性质,问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
9.分治法的基本思想是什么?
合并排序的基本思想是什么?
请分别简述之。
分治法的基本思想:
将n个输入分成k个不同子集合,得到k个不同的可独立求解的子问题,其中1合并排序基本思想:
将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合。
10.简述分析贪心算法与动态规划算法的异同。
贪心算法和动态规划算法都要求问题具有最优子结构性质,这是两类算法的一个共同点。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
蛮力法:
直接基于问题的描述
(1)蛮力法依赖的基本技术——扫描技术,即采用一定的策略将待求解问题的所有元素依次处理一次,从而找出问题的解
关键——依次处理所有元素
(2)基本的扫描技术——遍历
集合的遍历:
按元素序号
线性表的遍历:
按元素序号
树的遍历:
按前序、中序、后序、层次
图的遍历:
按深度优先、广度优先
(3)蛮力法可以作为某类问题时间性能的底限,来衡量同样问题的更高效算法。
(4)顺序查找:
从表的一端向另一端逐个将元素与给定值进行比较,若相等,则查找成功,给出该元素在表中的位置;若整个表检测完仍未找到与给定值相等的元素,则查找失败,给出失败信息。
3、算法编写及算法应用分析题:
四、算法理解题(本题10分)
根据优先队列式分支限界法,求下图中从v1点到v9点的单源最短路径,请画出求得最优解的解空间树。
要求中间被舍弃的结点用×标记,获得中间解的结点用单圆圈○框起,最优解用双圆圈◎框起。
3.根据优先队列式分支限界法,求下图中从v1点到v9点的单源最短路径,请画出求得最优解的解空间树。
要求中间被舍弃的结点用×标记,获得中间解的结点用单圆圈○框起(如
),最优解用双圆圈◎框起。
3.已知
,k=1,2,3,4,5,6,r1=5,r2=10,r3=3,r4=12,r5=5,r6=50,r7=6,求矩阵链积A1×A2×A3×A4×A5×A6的最佳求积顺序(要求给出计算步骤)。
解:
使用动态规划算法进行求解。
求解矩阵为:
1
2
3
4
5
6
1
0
150
330
405
1655
2010
2
0
360
330
2430
1950
3
0
180
930
1770
4
0
3000
1860
5
0
1500
6
0
1
2
3
4
5
6
1
0
1
2
2
4
2
2
0
2
2
2
2
3
0
3
4
4
4
0
4
4
5
0
5
6
0
因此,最佳乘积序列为(A1A2)((A3A4)(A5A6)),共执行乘法2010次。
8、试写出用分治法对数组A[n]实现快速排序的算法。
解:
用分治法求解的算法代码如下:
intpartition(floatA[],intp,intr)
{
inti=p,j=r+1;
floatx=a[p];
while
(1){
while(a[++i]while(a[--j]>x);
if(i>=j)break;
a[i]
};
a[p]=a[j];
a[j]=x;
returnj;
}
voidQuicksort(floata[],intp,intr)
{
if(pintq=partition(a,p,r);
Quicksort(a,p,q-1);
Quicksort(a,q+1,r);
}
};
Quicksort(a,0,n-1);
16、试写出用分治法对一个有序表实现二分搜索的算法。
解:
解答如下:
Template
intBinarySearch(Typea[],constType&x,intn)
{//假定数组a[]已按非递减有序排列,本算法找到x后返回其在数组a[]中的位置,//否则返回-1
intleft=0,right=n-1;
while(left<=right){
intmiddle=(left+right)/2;
if(x==a[middle])returnmiddle+1;
if(x>a[middle])left=middle+1;
elseright=middle-1;
}
return-1;
}
18、假设有7个物品,它们的重量和价值如下表所示。
若这些物品均不能被分割,且背包容量M=150,使用回溯方法求解此背包问题,请写出状态空间搜索树。
物品
A
B
C
D
E
F
G
重量
35
30
60
50
40
10
25
价值
10
40
30
50
35
40
30
解:
按照单位效益从大到小依次排列这7个物品为:
FBGDECA。
将它们的序号分别记为1~7。
则可生产如下的状态空间搜索树。
其中各个节点处的限界函数值通过如下方式求得:
a.
b.
c.
d.
e.
f.
g.
h.
i.
j.
在Q1处获得该问题的最优解为
,背包效益为170。
即在背包中装入物品F、B、G、D、A时达到最大效益,为170,重量为150。
实验程序
1.某地刑侦大队对涉及六个嫌疑人的一桩疑案进行分析:
(1)A、B至少有一人作案;
(2)A、E、F三人中至少有两人参与作案;(3)A、D不可能是同案犯;(4)B、C或同时作案,或与本案无关;(5)C、D中有且仅有一人作案;(6)如果D没有参与作案,则E也不可能参与作案。
试设计算法将作案人找出来。
2.将1,2...9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:
2:
3的比例,试求出所有满足条件的三个三位数。
(2)
1.实验分析
实验一中,将那些涉及的条件用括号括起来,再用&&连接起来,由于有六个人,则需用六个for循环,将那作案与非作案设为0和1,然后用蛮力法去判断。
实验二中,首先要得出3个3元数中分别由哪三个数组成,再判断这九个数有没有重复的数,然后,再用蛮力法去判断是否成倍数关系,再将满足条件的输出。
特别要注意怎么判断那九个数字是不是有重复的用什么方法。
七、算法设计题(本题10分)
通过键盘输入一个高精度的正整数n(n的有效位数≤240),去掉其中任意s个数字后,剩下的数字按原左右次序将组成一个新的正整数。
编程对给定的n和s,寻找一种方案,使得剩下的数字组成的新数最小。
【样例输入】
178543
S=4
【样例输出】
13
1.7分
为了尽可能地逼近目标,选取的贪心策略为:
每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字,否则删除第一个递减区间的首字母。
然后回到串首,按上述规则再删除下一个数字。
重复以上过程s次,剩下的数字串便是总是的解。
2.8分
stringMinNum(stringn,ints)
{
while(s>0)
{
unsignedinti=0;//从串首开始找
while(ii++;
n.erase(i,1);//删除字符串n中索引为i的字符
s--;
}
while(n.length()>1&&n.at(0)=='0')
n.erase(0,1);//删除串首可能产生的无用零
returnn;
}