算法设计整理

(外加一段蓝桥杯经验总结:
1、注意阅读题目中的每一行字,都可能成为条件来源
2,、注意把握时间
3、切记不要理解错题目要求,一定要读清楚题目要求!!!
4、适当对答案进行验算
5、分值分配:3 5 8 11 13 15 19 21 25 30
6、填空题多试几次
7、输入答案注意用英文输入
8.日期类用excel计算天数结果+1,计算日期结果-1(补充:加一还是
不加要根据题目中所给的测试用例进行判断)
9.全排列用到数组和next_permutation(a,a+x),并且头文件)

1.算法和程序的区别
算法是指解决问题的一种方法或一个过程。
算法是若干指令的有穷序列,满足性质:
(1)输入:有外部提供的量作为算法的输入。
(2)输出:算法产生至少一个量作为输出。
(3)确定性:组成算法的每条指令是清晰,无歧义的。
(4)有限性:算法中每条指令的执行次数是有限的,执行每条指令的时间也是有限的。
(5)可行性:算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。
程序是算法用某种程序设计语言的具体实现。
程序可以不满足算法的性质(4)。
例如操作系统,是一个在无限循环中执行的程序,因而不是一个算法。

2.时间空间复杂度
算法的复杂性有时间复杂性 和 空间复杂性之分,衡量一个算法好坏的标准是 时间复杂度高低。

  1. P、NP、NPC问题
    P(Polynomial问题):也即是多项式复杂程度的问题。
    NP就是Non-deterministic Polynomial的问题,也即是多项式复杂程度的非确定性问题。
    1)NPC(NP Complete)问题,这种问题只有把解域里面的所有可能都穷举了之后才能得出答案,这样的问题是NP里面最难的问题,这种问题就是NPC问题。

4.分治法的基本思想
分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问
题互相独立且与原问题相同;对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止;将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。

5.二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。

6.快速排序
基本思想:对于输入的子数组a[p:r],按以下三个步骤进行排序。
1)分解(Divide):以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1,r],使a[p:q-1]中任何一个元素小于等于a[q],而a[q+1,r]中任何一个元素大于等于a[q]。下标q在划分过程中确定。
2)递归求解(Conquer):通过递归调用快速排序算法分别对a[p:q-1]和a[q+1:r]进行排序。
3)合并(Merge):由于对a[p:q-1]和a[q+1:r]的排序是就地进行的,所以在a[p:q-1]和a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]就已排好序。

7.动态规划算法的基本思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。
但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。

8.动态规划算法的基本要素
一、最优子结构
矩阵连乘计算次序问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质。
同一个问题可以有多种方式刻划它的最优子结构,有些表示方法的求解速度更快(空间占用小,问题的维度低)
二、重叠子问题
递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。这种性质称为子问题的重叠性质。
三、备忘录方法
备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。

11.贪心算法的基本要素
可以用贪心算法求解的问题一般具有2个重要的性质:贪心选择性质和最优子结构性质。
1.贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
2.最有子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
3.贪心算法与动态规划算法的差异
贪心算法和动态规划算法都要求问题具有最优子结构性质,这是2类算法的一个共同点。

12.最有装载
1、算法描述
最优装载问题可用贪心算法求解。采用重量最轻者先装的贪心选择策略,可产生最优装载问题的最优解。

2、贪心选择性质
可以证明最优装载问题具有贪心选择性质。
3、最优子结构性质
最优装载问题具有最优子结构性质。
由最优装载问题的贪心选择性质和最优子结构性质,容易证明算法loading的正确性。
算法loading的主要计算量在于将集装箱依其重量从小到大排序,故算法所需的计算时间为 O(nlogn)。

13.回溯法的算法框架

  1. 问题的解空间
    问题的解向量:回溯法希望一个问题的解能够表示成一个n元式(x1,x2,…,xn)的形式。
    显约束:对分量xi的取值限定。
    隐约束:为满足问题的解而对不同分量之间施加的约束。
    解空间:对于问题的一个实例,解向量满足显式约束条件的所有多元组,构成了该实例的一个解空间。
  2. 回溯法的基本思想
    回溯法的基本思想是在一棵含有问题全部可能解的状态空间树上进行深度优先搜索,
    解为叶子结点。搜索过程中,每到达一个结点时,则判断该结点为根的子树是否含有问题的解,如果可以确定该子树中不含有问题的解,则放弃对该子树的搜索,退回到上层父结点,继续下一步深度优先搜索过程。在回溯法中,并不是先构造出整棵状态空间树,再进行搜索,而是在搜索过程,逐步构造出状态空间树,即边搜索,边构造。
    3.递归回溯
    回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。
    void backtrack (int t)
    {
    if (t>n) output(x);
    else
    for (int i=f(n,t);i<=g(n,t);i++) {
    x[t]=h(i);
    if (constraint(t)&&bound(t)) backtrack(t+1);
    }
    }
    4.迭代回溯
    采用树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程。
    void iterativeBacktrack ()
    {
    int t=1;
    while (t>0) {
    if (f(n,t)<=g(n,t))
    for (int i=f(n,t);i<=g(n,t);i++) {
    x[t]=h(i);
    if (constraint(t)&&bound(t)) {
    if (solution(t)) output(x);
    else t++;}
    }
    else t–;
    }
    }
    5.子集树与排列树
    遍历子集树需O(2n)计算时间
    void backtrack (int t)
    {
    if (t>n) output(x);
    else
    for (int i=0;i<=1;i++) {
    x[t]=i;
    if (legal(t)) backtrack(t+1);
    }
    }
    遍历排列树需要O(n!)计算时间
    void backtrack (int t)
    {
    if (t>n) output(x);
    else
    for (int i=t;i<=n;i++) {
    swap(x[t], x[i]);
    if (legal(t)) backtrack(t+1);
    swap(x[t], x[i]);
    }
    }

14.0-1背包问题
解空间:子集树
可行性约束函数:
上界函数:
template<class Typew, class Typep>
Typep Knap<Typew, Typep>::Bound(int i)
{// 计算上界
Typew cleft = c - cw; // 剩余容量
Typep b = cp;
// 以物品单位重量价值递减序装入物品
while (i <= n && w[i] <= cleft) {
cleft -= w[i];
b += p[i];
i++;
}
// 装满背包
if (i <= n) b += p[i]/w[i] * cleft;
return b;
}

15.分支限界法的基本思想
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

16.0-1背包问题
算法的思想
首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。
在下面描述的优先队列分支限界法中,节点的优先级由已装袋的物品价值加上剩下的最大单位重量价值的物品装满剩余容量的价值和。
算法首先检查当前扩展结点的左儿子结点的可行性。如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列。当扩展到叶节点时为问题的最优值。
上界函数
while (i <= n && w[i] <= cleft) // n表示物品总数,cleft为剩余空间
{
cleft -= w[i]; //w[i]表示i所占空间
b += p[i]; //p[i]表示i的价值
i++;
}
if (i <= n) b += p[i] / w[i] * cleft; // 装填剩余容量装满背包
return b; //b为上界函数
分支限界搜索过程
while (i != n+1) {// 非叶结点
// 检查当前扩展结点的左儿子结点
Typew wt = cw + w[i];
if (wt <= c) {// 左儿子结点为可行结点
if (cp+p[i] > bestp) bestp = cp+p[i];
AddLiveNode(up, cp+p[i], cw+w[i], true, i+1);}
up = Bound(i+1);
// 检查当前扩展结点的右儿子结点
if (up >= bestp) // 右子树可能含最优解
AddLiveNode(up, cp, cw, false, i+1);
// 取下一个扩展节点(略)
}

17.随机数
随机数在随机化算法设计中扮演着十分重要的角色。在现实计算机上无法产生真正的随机数,因此在随机化算法中使用的随机数都是一定程度上随机的,即伪随机数。
线性同余法是产生伪随机数的最常用的方法。由线性同余法产生的随机序列a0,a1,…,an满足,其中b0,c0,dm。d称为该随机序列的种子。如何选取该方法中的常数b、c和m直接关系到所产生的随机序列的随机性能。这是随机性理论研究的内容,已超出本书讨论的范围。从直观上看,m应取得充分大,因此可取m为机器大数,另外应取gcd(m,b)=1,因此可取b为一素数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值