算法
文章平均质量分 96
各种算法。参考书籍有:王晓东《计算机算法设计与分析》,以及我算法课的ppt
迷雾总会解
我来,我见,我征服!
展开
-
算法相关概述(算法,程序,复杂度分析,基本结构,表示方法,NP完全性理论,最优化问题,判定问题,P类问题,NP类问题)
算法(Algorithm)的定义 算法是指解决问题的一种方法或一个过程。 算法是对特定问题求解步骤的一种描述,是若干指令的有穷序列。算法(Algorithm)的性质输入:有外部提供的量作为算法的输入输出:算法产生至少一个量作为输出确定性:组成算法的每条指令是清晰、无歧义的。相同的输入只能有唯一的输出结果;算法在一定条件下,只有一条执行路径;有限性:算法中每条指令的执行次数是有限的,每条指令的执行时间也是有限的程序(Program) 程序是算法用某种程序设计语言的具体实现 程序可以原创 2020-07-02 23:30:29 · 1185 阅读 · 0 评论 -
递归思想的介绍(阶乘函数,Fibonacci数列,Ackerman函数,整数划分问题,Hanoi塔问题)
递归的概念 递归算法:直接或间接地调用自身的算法。 递归函数:用函数自身给出定义的函数。 使用递归技术使得算法的描述简捷且易于理解。例1 阶乘函数 阶乘函数可递归地定义为: 边界条件与递归方程是递归函数的二个要素,递归函数只有具备了这两个要素,才能在有限次计算后得出结果。 阶乘函数的递归调用算法:int factorial(int n){ if (n ==0) return 1; return n*factorial(n-1) ;}例2 Fibonacci数列原创 2020-06-30 11:16:28 · 654 阅读 · 0 评论 -
分治法思想的介绍(大整数的乘法,Strassen矩阵乘法,棋盘覆盖问题,二分搜索,快速排序,合并排序,线性时间选择)
分治法基本思想将一个难以直接解决的大问题,分割成一些规模较小的k个相同问题,以便·各个击破,分而治之·。对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为若干个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。 递归是实现分治算法思想的技术。????查看递归的介绍 合并排序的例子分治法的适用条件分治法所能解决的问题一般具有以下几个特征:该问题的规模缩小到一定的程度就可以原创 2020-06-30 13:19:01 · 1201 阅读 · 0 评论 -
动态规划思想的介绍(矩阵连乘问题,最长公共子序列,流水线作业调度问题,0-1背包问题)
动态规划基本思想动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题但是,分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。可以用一个表来纪录所有已解决的子问题的答案,以后需要时,只需查询此表即可。基本步骤找出最优解的性质,并刻画其结构特征。递归地定义最优值。以自底向上的方式计算最优值原创 2020-07-02 01:23:38 · 372 阅读 · 0 评论 -
贪心思想的介绍(活动安排问题,0-1背包问题,最优装载,哈夫曼编码,单源最短路径,最小生成树(Prim,Kruskal),汽车加油问题)
何为贪心 假设有四种硬币:二角五分、一角、五分和一分。现要找给顾客六角三分。 显然,会拿出2个二角五分、1个一角和3个一分的硬币交给顾客。 贪心方法思路:首先选出一个面值不超过六角三分的最大硬币,即二角五分,然后在剩余数中再选最大面值的硬币,依此类推,得到其解。 若硬币面值改为:一角一分、五分和一分,而要找给顾客一角五分钱。 用贪心算法将找给1个一角一分和4个一分的硬币。然而,3个五分硬币是最好的找法。 此时,贪心算法没有得到整体最优解。但通常可得到最优解的很好近似。 顾名思义,贪心算法总是原创 2020-07-02 16:23:54 · 1343 阅读 · 0 评论 -
回溯法思想的介绍(旅行售货员问题,装载问题, 0-1背包问题,图的m着色问题)
基本介绍 当需要找出问题的解集,或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。 回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。 在问题的解空间树中,回溯法按深度优先策略,从根结点出发搜索解空间树。基本思想扩展结点:一个正在产生儿子的结点活结点:一个自身已生成但其儿子还没有全部生成的节点死结点:一个所有儿子已经产生的结点确定了解空间的组织结构后,回溯法从开始节点出发,以深度优先方式搜索整个解空间,这个开始节点成为活节点,同时成原创 2020-07-02 21:24:32 · 882 阅读 · 0 评论 -
分支限界法思想的介绍(装载问题,旅行售货员问题,0-1背包问题)
类似于回溯法,分支限界法也是一种在问题的解空间树T上搜索问题解的算法。分支限界法和回溯法(1)求解目标:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。(2)搜索方式:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最大效益优先(最小耗费) 的方式搜索解空间树。分支限界法特点每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。.原创 2020-06-22 23:16:10 · 1397 阅读 · 0 评论 -
汉诺塔问题-递归实现
问题描述 设A,B,C是3个塔座。开始时,在A上有n个圆盘,这些圆盘自下而上,由大到小地叠在一起。各圆盘从小到大编号为1,2,…,n。 问题:现要求将A上的这一叠圆盘移到B上,并仍按同样顺序叠置。 在移动圆盘时应遵守以下移动规则:规则1:每次只能移动1个圆盘;规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘之上;规则3:在满足规则1,2的前提下,可将圆盘移至A,B,C中任一塔座上。解题思路 1. 将上面n-1个盘子从A座移到C座 2. 将1个盘子(最底下的、最大的盘子)原创 2020-06-30 11:13:08 · 764 阅读 · 0 评论 -
棋盘覆盖问题-分治算法
问题描述 棋盘覆盖问题。有一个2k∗2k的方格棋盘,恰有一个方格是黑色的,其他为白色。你的任务是用包含3个方格的L型牌覆盖所有白色方格。黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖。如图所示为L型牌的4种旋转方式。思路分析分治三步骤 划分问题:将2k∗2k的棋盘划分为2k−1∗2k−1 这样的子棋盘4块。 递归求解:递归填充各个格子,填充分为四个情况,在下面会有解释,递归出口为k=0也就是子棋盘方格数为1。 合并问题:不需要合并子问题。递归填充原创 2020-05-17 12:03:53 · 1875 阅读 · 0 评论 -
二分搜索-分治算法
问题描述 给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。分析 是否满足分治法的特征? √ 该问题的规模缩小到一定的程度就可以容易地解决; √ 该问题可以分解为若干个规模较小的相同问题; √ 分解出的子问题的解可以合并为原问题的解; √ 分解出的各个子问题是相互独立的。 给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。 分析:如果n=1即只有一个元素,则只要比较这个元素和x就可以确定x是否在表中。因此这个问原创 2020-06-30 12:21:22 · 2261 阅读 · 0 评论 -
快速排序-分治算法
基本思想 基于分治策略的排序在快速排序中,记录的比较和交换是从两端向中间进行的,关键字较大(小)的记录一次就能交换到后(前)面单元,总的比较和移动次数较少。 基本思想:对于输入子数组a[p: r]分解: 以a[p]为基准元素将a[p: r]划分成三段a[p: q-1], a[q] 和a[q+1:r], 使得a[p: q-1]中任一元素<= a[q], a[q+1:r]中任一元素>= a[q]. q在划分过程中确定.递归求解: 分别对a[p: q-1]和a[q+1:r]进行递归排序.原创 2020-06-30 17:04:18 · 2195 阅读 · 0 评论 -
合并排序-分治算法
基本思想 将n个元素分成2个大小相同的子集合,分别对子集合进行排序,最终将排好序的子集合合并为有序集合。n=1时中止。算法分析 当最小规模为4时,进行排序和归并,将已经比较好的较小的值依次排好序放在一个临时的数组中 上面的是规模为4时的分析,归并算法中,一般把规模缩小到2,并开始进行排序和归并归并算法复杂度分析 ???? 可参考分治的基本复杂度分析 计算过程 原式等价于 T(n)=2T(n/2)+n 递推得: 2T(n/2)=2(2T(n/22)+n/2)=22T原创 2020-06-30 16:22:56 · 996 阅读 · 0 评论 -
快排和二分搜索的实验记录
#include<iostream>using namespace std;int getMiddler(int arr[],int start_,int end_);//先进行快排,将我们的数组进行排序,再进行二分搜索void quickSort(int arr[],int startV,int endV){ if(startV<endV){ int mid=getMiddler(arr,startV,endV);原创 2020-05-17 11:07:59 · 452 阅读 · 0 评论 -
线性时间选择-分治算法
问题描述 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。在线性时间内O(n)?k=1; 最小元素 O(n)k=n; 最大元素 O(n)k=(n+1)/2: 中位数 O(n)?算法思想 线性时间选择问题的分治法:模仿快速排序算法,找第k小元素。 思想:对输入数组递归划分,但仅对划分出的子数组之一进行递归处理。主要算法template<class Type&原创 2020-06-30 22:30:02 · 3544 阅读 · 1 评论 -
线性时间选择-分治算法(冒泡和快速)
分治法(线性时间选择)*线性时间选择问题*:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的)。随机划分线性选择 线性时间选择随机划分法可以模仿随机化快速排序算法设计。基本思想是***对输入数组进行递归划分,与快速排序不同的是,它只对划分出的子数组之一进行递归处理***。c++程序//2d9-1 随机划分线性时间选择#...原创 2020-04-27 16:37:24 · 945 阅读 · 0 评论 -
矩阵连乘问题-动态规划(自底向上,自顶向下,重叠问题)
【问题描述】 给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10100,1005和550,采用(A1A2)A3,乘法次数为101005+10550=7500次,而采用A1(A2A3),乘法次数为100550+10100*...原创 2020-05-07 12:25:43 · 3143 阅读 · 0 评论 -
流水线作业调度问题-动态规划(运用Johnson算法)
思路的重点算法完整代码 把在M1上工作的时间看做是先行工序时间,M2上的工作时间看成后行工序时间。 如果某个作业的M1时间>M2时间,它就是后行工序;反之,就是先行工序时间。#include<stdio.h>#include<iostream>#include<algorithm>#define n 6 //6个作业using namespace std;int M1[n]={2,7,6,4,6,8};int .原创 2020-05-19 12:27:00 · 15063 阅读 · 10 评论 -
最长公共子序列-动态规划
定义描述 若给定序列X={x1x_1x1,x2x_2x2,…,xmx_mxm},则另一序列Z={z1z_1z1,z2z_2z2,…,zkz_kzk} 是X的子序列,是指存在一个严格递增下标序列{i1i_1i1,i2i_2i2,…,iki_kik}使得对于所有j=1,2,…,k有:zjz_jzj = xijx_{i_j}xij 。 例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7} 给定2个序列X和Y,当另原创 2020-07-02 01:20:42 · 1386 阅读 · 0 评论 -
0-1背包问题-动态规划
问题描述 给定n个物品和一个背包。物品i的重量为wi,价值为vi,背包容量为c。 如何选择装入背包中的物品,使得装入背包的物品的价值最大? 每种物品i只有两种选择,装入或者不装入,既不能装入多次,也不能只装入一部分。 此问题称为0-1背包问题。问题形式化描述 问题的形式描述是:给定c>0,wiw_iwi>0,viv_ivi>0,1≤i≤n,求n元0-1向量(x1x_1x1, x2x_2x2, …, xnx_nxn),使得 (物品i的重量为wi,价值为vi,背包容量为c。)最优原创 2020-07-02 16:10:27 · 4774 阅读 · 1 评论 -
活动安排问题-贪心
问题描述 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。 该问题要求高效地安排一系列争用某一公共资源的活动。 贪心算法使得尽可能多的活动能兼容地使用公共资源。 设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。 每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi, 且si <fi 。 如果选择了活动i,则它在[si, fi)内占用资源。 若[s原创 2020-07-02 16:34:42 · 1129 阅读 · 0 评论 -
0-1背包问题-贪心(不适合用贪心)
提示 0-1背包问题不适合用贪心法来求解。一下仅仅是来模拟和解释为什么不能用贪心问题描述给定n种物品和一个背包。物品i的重量是wi,其价值为vi,背包的容量为c。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。基本步骤计算每种物品单位重量的价值vi/wi依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内原创 2020-07-02 16:51:57 · 8961 阅读 · 0 评论 -
最优装载-贪心
问题描述有一批集装箱,要装上一艘载重量为c的轮船。其中集装箱i的重量为wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。装载问题的形式化描述算法描述 最优装载问题可用贪心算法求解。采用重量最轻者先装的贪心选择策略,可产生最优装载问题的最优解。核心算法Template <class Type>void Loading(int x[ ], Type w[ ], Type c, int n){ int *t = new i原创 2020-07-02 17:13:35 · 598 阅读 · 0 评论 -
哈夫曼编码-贪心
哈夫曼树的定义 n个叶结点,权分别为w1,w2,···,wn的二叉树中,带权路径长度WPL最小的二叉树叫哈夫曼树(Huffman Tree ), 即:最优二叉树哈夫曼原理1)将字符集中每个字符c出现的频率f©作为权值2)根据给定的权值{w1,w2,···,wn}构造n个二叉树F={T1,T2,···,Tn}, 每个Ti只有一个根结点,权为wi。3)在F中选取两棵根结点的权值最小的树构成一棵新的二叉树,其根的权值为左右子树根的权值的和。4)F中删去这两棵树,加上新得的树。5)重复2)3)直到只原创 2020-06-22 15:35:54 · 350 阅读 · 0 评论 -
单源最短路径-贪心(Dijkstra (迪杰斯特拉),有向图,无向图)
问题描述 给定一个图G = (V, E),其中每条边的权是一个非负实数。另外给定顶点集合V中的一个顶点v,称为源。 问题:求从源v到所有其它各个顶点的最短路径。问题分析 单源最短路径问题的贪心选择策略:选择从源v出发,目前用最短的路径所到达的顶点,这就是目前的局部最优解。基本思想 设置一个集合S,初始时S中仅含有源v,然后不断地用贪心选择来扩充集合S ,即:从源v出发,选择用最短的路径所到达的顶点u,加入到集合S中,直至S包含所有V中顶点。 把从源v到顶点u中间只经过S中顶点的路称为从源v原创 2020-07-02 17:44:13 · 1929 阅读 · 2 评论 -
最小生成树-贪心(Prim算法(普里姆算法))
问题描述 设G = (V, E)是一个无向连通带权图,即一个网络。E的每条边(v, w)的权为c[v][w]。 如果G的一个子图G’是一棵包含G的所有顶点的树,则称G’为G的生成树。 生成树的各边权的总和称为该生成树的耗费。 在G的所有生成树中,耗费最小的生成树称为G的最小生成树MST(minimum spanning tree) 。算法思想在保证连通的前提下依次选出权重较小的n – 1条边。G=(V, E)为无向连通带权图,令V={1, 2, …, n}。设置一个集合S ,初始化S =原创 2020-07-02 18:09:01 · 3753 阅读 · 0 评论 -
最小生成树-贪心(Kruskal算法(克鲁斯卡尔算法))
问题描述 设G = (V, E)是一个无向连通带权图,即一个网络。E的每条边(v, w)的权为c[v][w]。 如果G的一个子图G’是一棵包含G的所有顶点的树,则称G’为G的生成树。 生成树的各边权的总和称为该生成树的耗费。 在G的所有生成树中,耗费最小的生成树称为G的最小生成树MST(minimum spanning tree) 。算法思想在保证无回路的前提下依次选出权重较小的n – 1条边。贪心策略:如果(i, j)是E中尚未被选中的边中权重最小的,并且(i, j)不会与已经选择的边构原创 2020-07-02 18:46:10 · 3278 阅读 · 0 评论 -
汽车加油问题-贪心
问题描述 一辆汽车加满油后可行驶nkm 。旅途中有k个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。并计算最少加油次数。问题分析 根据贪心算法的贪心选择性质, 为了要使加油次数最少,就会选择离加满油的点远一点的加油站加油。 另外,当加满油之后,都要是此后的过程中使加油次数最少。每一次汽车中剩下的油不能再行驶到下一站时,就在该站加油。每一次加满油之后与起点具有相同的条件,可以看做一个新的起点,过程也是相同的。因此,该问题具有最优子结构性质核心代码nt greedy(原创 2020-07-02 19:00:16 · 1662 阅读 · 0 评论 -
旅行售货员问题-回溯法
问题描述: 某售货员要到若干城市去推销商品,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到住地的路线,使总的路程最短。 结果为: 1 3 2 4 1算法描述:回溯法,序列树, 假设起点为 1。算法开始时 x = [1, 2, 3, …, n]x[1 : n]有两重含义 x[1 : i]代表前 i 步按顺序走过的城市, x[i + 1 : n]代表还未经过的城市。利用Swap函数进行交换位置。若当前搜索的层次i = n 时,处在排列树的叶节点的父节点上,此原创 2020-06-22 16:05:12 · 24942 阅读 · 5 评论 -
装载问题-回溯法
问题描述问题分析例子演示分析过程算法思路用树表示解空间,则解为n元向量{x1, … ,xn }, xi∈{0, 1} 。约束条件: 当前搜索的层i <= n时,当前扩展结点Z为子集树的内部结点,仅当满足cw+w[i] <= c时进入左子树,x[i]=1; 当cw+w[i] > c ,在以结点Z为根的子树中所有结点都不满足约束条件,因而该子树中解都是不可行解,因而将在该子树删去。限界函数: 由于是最优化问题, 可利用最优解性质进一步剪去不含最优解的子树: 设原创 2020-06-15 11:11:02 · 12002 阅读 · 2 评论 -
0-1背包问题-回溯法
算法描述 0-1背包问题是子集选取问题。一般情况下,0-1背包问题是NP难得。0-1背包问题的解空间可用子集树 表示。在搜索解空间的时,只要其左儿子节点是一个可行节点,搜索就进去其左子树(约束条件)。当右子树中可能包含最优解时才进入右子树搜索(限界函数)。否则就将右子树剪去。 计算右子树中解的上界的更好方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入物品的一部分而装满背包。由此得到的价值是右子树中解的上界。例如,对于0-1背包问题的一个实例,n = 4, c = 7, p原创 2020-06-15 13:12:16 · 13498 阅读 · 7 评论 -
图的m着色问题-回溯法
问题描述 给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。例如:点个数n=7,颜色m=3的涂色方案算法设计 一般连通图的可着色问题,不仅限于可平面图。 给定图G=(V,E)和m种颜色,如果该图不是m可着色,给出否定回答;若m可原创 2020-06-15 13:40:13 · 18188 阅读 · 1 评论 -
装载问题-分支限界法(队列式分支限界法,优先队列式分支限界法)
问题描述 有n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且 问题: 是否有一个合理的装载方案,可将这n个集装箱装上这2艘轮船?如果有,找出一种装载方案。例如:当n=3, c1=c2=50(1)若w=[10, 40, 40] 可将集装箱1和集装箱2装上第一艘轮船,而将集装箱3装上第二艘轮船;(2)如果w=[20, 40, 40] 则无法将这3个集装箱都装上船;基本思路已证明,如果一个给定装载问题有解,则采用下面的策略可得到最优装原创 2020-06-22 22:43:42 · 30122 阅读 · 7 评论 -
旅行售货员问题-分支限界法(优先队列式分支限界法)
问题描述:某售货员要到若干城市去推销商品,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到住地的路线,使总的路程最短。 结果为: 1 3 2 4 1 问题分析解旅行售货员问题的优先队列式分支限界法用优先队列存储活结点表。活结点m在优先队列中的优先级定义为:活结点m对应的子树费用下界lcost。lcost=cc+rcost,其中,cc为当前结点费用,rcost为当前顶点最小出边费用加上剩余所有顶点的最小出边费用和。优先队列中优先级最大的活结点成为下一个扩展结点原创 2020-06-28 14:58:18 · 31116 阅读 · 23 评论 -
0-1背包问题-分支限界法(优先队列分支限界法)
算法的思想首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。在优先队列分支限界法中,结点的优先级定义为:以结点的价值上界作为优先级(由bound函数计算出)步骤算法首先根据基于可行结点相应的子树最大价值上界优先级,从堆中选择一个节点(根节点)作为当前可扩展结点。检查当前扩展结点的左儿子结点的可行性。如果左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界函数约束时,才将它加入子集树和活结点优先队原创 2020-06-22 23:02:33 · 49029 阅读 · 22 评论 -
最小重量机器设计问题-分支限界法(优先队列分支限界法)
问题描述: 设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设是从供应商j处购得的部件i的重量,是相应的价格。 试设计一个优先队列式分支限界法,给出总价格不超过d的最小重量机器设计。代码#include<iostream>#include<queue>using namespace std;int n; //部件数量int m; //供应商数量int d; //价格上限int bestw; //最小的重量int原创 2020-07-03 23:10:42 · 9169 阅读 · 8 评论