第4章 基本的算法策略(2011-10-10)
基本的算法策略
任务分配问题就是在分配成本矩阵中的每一行 选取一个元素,这些元素分别属于不同的列, 选取一个元素,这些元素分别属于不同的列,并且 元素之和最小。 元素之和最小。
可以用一个n元组 可以用一个 元组(j1, j2, …, jn)来描述任务分配问题的一个可能 元组 来描述任务分配问题的一个可能 其中第i个分量 个分量j 行中选择的列号, 解,其中第 个分量 i(1≤i≤n)表示在第 行中选择的列号, ≤ ≤ )表示在第i行中选择的列号 因此用蛮力法解决任务分配问题要求生成整数1~n的全排列, 的全排列, 因此用蛮力法解决任务分配问题要求生成整数 的全排列 然后把成本矩阵中的相应元素相加来求得每种分配方案的总 成本,最后选出具有最小和的方案。 成本,最后选出具有最小和的方案。 序号 1 2 3 4 5 6 分配方案 1, 2, 3 1, 3, 2 2, 1, 3 2, 3, 1 3, 1, 2 3, 2, 1 总成本 9+4+1=14 9+3+8=20 2+6+1=9 2+3+5=10 7+6+8=21 7+4+5=16
证明0/1背包问题满足最优性原理。 证明 背包问题满足最优性原理。 背包问题满足最优性原理 是所给0/1背包问题的一个最优解 设(x1, x2, …, xn)是所给 背包问题的一个最优解,则 是所给 背包问题的一个最优解, ( x2, …, xn)是下面一个子问题的最优解: 是下面一个子问题的最优解: 是下面一个子问题的最优解
最优分配方案是将任务2 任务1 任务3 最优分配方案是将任务2,任务1,任务3分别分配给人 员1,人员2,人员3,将使总成本达到最小值9。 人员2 人员3 将使总成本达到最小值9
算法教学策略
算法教学策略随着计算机的发展,算法成为计算科学的重要组成基础,算法思想已经成为现代人应具备的一种数学素养。
在世界上很多发达国家算法早已成为中学教学的重要内容。
我国2003年颁布了《高中数学课程标准》后,算法作为具体的教学内容进入中学数学的教科书中。
随着新课程实施的不断深入,算法“教与学”的有关问题逐渐被人们所关注。
由于算法内容对大部分中学数学老师来说是比较陌生的,在实际教学中又没有现成的经验可以借鉴,因此给我们的教学带来了全方位的挑战。
本研究立足于算法教学实践,重点从算法初步学习内容的特点出发,借鉴布鲁姆的教育目标分类学的理论从教学目标分析入手,在对学生学习基础和学生认知特点进行科学分析的基础上,探讨一种可行性较高的教学模式。
研究过程中,首先在梳理算法知识结构的基础上,运用教育目标分类学理论对算法知识从知识维度和认知维度进行教学目标定位。
然后设计详细教学过程:根据教学目标中涉及的所有知识点,制定要实现的总目标的过程中必须完成的教学子目标,而后依据算法知识特点及课程标准要求达到的程度安排教学方法,从而完成教学活动设计和教学顺序安排。
最后,通过教学实施,对教学效果进行调查研究。
通过本研究得到的主要结论如下:1.目标分类教学策略对算法初步的教与学有显著的促进作用。
2.算法初步的学习过程既要注重算法思想的培养,又要重视技能方面的训练。
3.算法教学要重视案例的选取,重视调动学生学习的兴趣,从简单有趣的案例入手,让学生循序渐进的领悟算法的内涵。
让学生经历认知——模仿——理解——运用——分析——评价的过程是目标教学的指导思想。
算法教学策略(一)充分激发学生学习算法的兴趣爱因斯坦曾经说:兴趣是最好的老师。
瓦特从观察蒸汽冲起水壶盖的兴趣开始发明了蒸汽机,是人类的工业文明步入了崭新的蒸汽机时代,牛顿对树上掉落的苹果产生浓厚的兴趣,发明了万有引力定律,通过对两种算法------辗转相处法和更相减损术,使学生在欣赏中外古代数学优秀成果的过程中,体会两种算法的异曲同工之妙,介以激发学生学习的兴趣算法教学策略(二)既要讲算则又要讲算理在教学中,要注意不要把算则讲成单独的算法语言或程序设计,要体现数学与算法的有机结合,让学生理解数学再利用算法在解决问题中的作用以及算法对学习数学的要求。
算法设计指导教程
算法设计指导教程一、引言算法是计算机科学中非常重要的概念,它是解决问题的一种方法论。
在计算机科学的发展过程中,众多优秀的算法被提出并应用于各个领域。
本文旨在为读者提供一份算法设计的指导教程,帮助读者理解和应用常用的算法。
二、算法设计的基本原则1. 算法的可读性和可理解性:良好的算法应该具备清晰明了的逻辑结构,使得他人能够快速理解和使用。
2. 算法的高效性:算法应该能够在合理的时间内解决问题,尽量避免无效的计算和重复的操作。
3. 算法的正确性:算法在解决问题时应该能够得到正确的结果,不产生错误或歧义。
4. 算法的鲁棒性:算法应该能够处理各种异常情况,具备一定的容错能力。
三、算法设计的基本步骤1. 确定问题:首先,需要明确问题的具体描述和要求,明确问题的输入和输出。
2. 分析问题:根据问题的特点,进行问题分析,找出问题的关键点和难点。
3. 设计算法:根据问题的特点和分析结果,设计合适的算法,可以参考已有的算法或者创造新的算法。
4. 实现算法:将算法转化为具体的计算机程序,可以使用编程语言进行实现。
5. 测试算法:对实现的算法进行测试,验证算法的正确性和效率。
6. 优化算法:根据测试结果,对算法进行优化,提高算法的效率和性能。
7. 文档化算法:根据实现的算法编写详细的文档,包括算法的描述、输入输出的格式和示例等。
四、常用的算法设计方法1. 贪心算法:贪心算法是一种简单而有效的算法设计方法,它在每一步选择中都采取当前状态下的最优选择,从而希望能够达到全局最优解。
2. 分治算法:分治算法将问题划分为多个子问题,分别解决每个子问题,最后将子问题的解合并得到原问题的解。
3. 动态规划算法:动态规划算法是一种将问题划分为多个阶段,并记录每个阶段的最优解的方法,通过递推来得到最终的解。
4. 回溯算法:回溯算法是一种递归的算法设计方法,通过尝试所有可能的解,并在尝试过程中逐步排除不符合要求的解,最终找到符合要求的解。
《基本算法》教案
《基本算法》教案第一章:算法概述1.1 算法的定义介绍算法的概念和重要性解释算法在解决问题中的作用1.2 算法的特性讨论算法的准确性和效率探讨算法的可读性和可维护性1.3 算法的设计方法介绍常见的算法设计方法,如贪心法、分治法、动态规划法等第二章:简单的排序算法2.1 冒泡排序算法介绍冒泡排序的原理和步骤编写冒泡排序的伪代码2.2 选择排序算法介绍选择排序的原理和步骤编写选择排序的伪代码2.3 插入排序算法介绍插入排序的原理和步骤编写插入排序的伪代码第三章:图的基本算法3.1 图的表示方法介绍图的邻接矩阵和邻接列表表示方法3.2 深度优先搜索算法介绍深度优先搜索的原理和步骤编写深度优先搜索的伪代码3.3 广度优先搜索算法介绍广度优先搜索的原理和步骤编写广度优先搜索的伪代码第四章:动态规划算法4.1 动态规划概述介绍动态规划的概念和应用场景解释动态规划的基本原理4.2 动态规划解题步骤讨论动态规划解题的步骤和技巧给出动态规划解题的一般框架4.3 常见的动态规划问题解决一些典型的动态规划问题,如背包问题、最长公共子序列等第五章:算法评估与优化5.1 算法评估概述介绍算法评估的目的和方法讨论评估算法性能的指标,如时间复杂度和空间复杂度5.2 算法优化技巧介绍常见的算法优化技巧,如避免重复计算、使用缓存等5.3 算法效率分析分析算法的时间复杂度和空间复杂度讨论如何选择合适的算法based on given requirements.第六章:分支界限法6.1 分支界限法概述介绍分支界限法的原理和应用解释分支界限法在解决优化问题上的优势6.2 分支界限法的实现步骤讨论分支界限法解决问题的步骤,包括建树、剪枝等编写分支界限法的伪代码6.3 典型的分支界限法问题解决一些典型的分支界限法问题,如0-1背包问题、最长路径问题等第七章:回溯法7.1 回溯法概述介绍回溯法的原理和应用解释回溯法在解决组合优化问题上的优势7.2 回溯法的实现步骤讨论回溯法解决问题的步骤,包括递归、剪枝等编写回溯法的伪代码7.3 典型的回溯法问题解决一些典型的回溯法问题,如八皇后问题、0-1背包问题等第八章:分支界限法与回溯法的比较8.1 分支界限法与回溯法的区别分析分支界限法与回溯法在解决问题时的不同策略讨论两种算法的适用场景和优缺点8.2 分支界限法与回溯法的结合介绍如何将分支界限法与回溯法结合以提高算法性能8.3 实际应用案例分析分析实际应用中分支界限法与回溯法的使用和效果第九章:启发式算法9.1 启发式算法概述介绍启发式算法的原理和应用解释启发式算法在解决NP难问题上的优势9.2 常见的启发式算法讨论常见的启发式算法,如遗传算法、模拟退火算法、蚁群算法等9.3 启发式算法的应用解决一些典型的启发式算法问题,如旅行商问题、作业调度问题等第十章:算法设计与分析总结10.1 算法设计方法总结回顾本课程所学的算法设计方法,如贪心法、分治法、动态规划法等10.2 算法评估与优化总结总结本课程所学的算法评估与优化技巧10.3 算法应用与未来趋势探讨算法在实际应用中的重要性分析算法在未来发展中的趋势和挑战第十一章:算法竞赛与算法模型11.1 算法竞赛简介介绍算法竞赛的背景和意义分析参加算法竞赛的准备工作和要求11.2 常见算法竞赛平台讨论常见的算法竞赛平台,如LeetCode、Codeforces、TopCoder等分析这些平台的特点和题目类型11.3 算法模型的建立介绍如何建立算法模型,包括问题的定义、数据的表示等讨论算法模型在算法竞赛中的应用和重要性第十二章:并行算法12.1 并行算法的基本概念介绍并行算法的基本概念,如并行计算、并发计算等解释并行算法在解决问题中的优势和挑战12.2 并行算法的实现方法讨论并行算法的实现方法,如多线程、多进程、分布式计算等分析不同实现方法的特点和适用场景12.3 典型的并行算法介绍一些典型的并行算法,如矩阵乘法、排序算法等讨论并行算法在实际应用中的性能优化问题第十三章:概率算法13.1 概率算法的概念与特点介绍概率算法的概念和特点,如随机性、不确定性和容错性解释概率算法在解决某些问题上的优势13.2 典型的概率算法讨论典型的概率算法,如蒙特卡洛算法、随机化算法等分析这些算法在实际应用中的效果和限制13.3 概率算法的应用解决一些典型的概率算法应用问题,如估算质数个数、求解最短路径等第十四章:算法伦理与安全性14.1 算法伦理概述介绍算法伦理的概念和重要性讨论算法伦理在数据隐私、歧视和透明度等方面的问题14.2 算法的安全性解释算法安全性的概念和重要性讨论算法安全性在密码学、网络安全等领域的应用14.3 算法伦理与安全性的实践指导给出在设计和实现算法时考虑伦理和安全的实践指导第十五章:算法发展趋势与展望15.1 算法研究的新领域介绍算法研究的新领域,如机器学习算法、量子算法等分析这些新领域的发展潜力和应用前景15.2 算法技术的创新与应用讨论算法技术的创新点,如自动调参、算法优化等分析算法技术在各个领域的应用和发展趋势15.3 算法教育的未来展望探讨算法教育在培养新一代算法人才方面的作用和挑战分析算法教育在未来发展中的趋势和机遇重点和难点解析1. 算法的定义、特性和设计方法:理解算法的概念、特性以及设计方法是学习算法的基础,对于后续算法的理解和应用具有重要意义。
实验项目二:算法的基本策略
《算法设计与分析》实验报告实验项目(二)算法的基本策略四、实验内容与步骤1、编写程序,分别用二分法和牛顿迭代法求解方程x3– 3x– 1 = 0在x = 2附近的实根,要求计算精确到小数点后7 位数字为止,并将求出的近似结果与理论值2cos20 比较误差大小。
设二分法的初始迭代区间为[1, 3],牛顿迭代法的起点为4。
2、将一X100 元的钞票换成1 元、2元、5 元和10 元的零钱,每种零钞至少一X,编写程序输出所有的换法,尽可能地提高算法效率。
3、用动态规划求解设备更新问题。
某人打算购买一辆新的小货车用于运货,货车的售价是22 万元人民币。
货车购买后,每年的各种保险费、养护费等费用如下表:如果5年内将货车售出,并再购买新车,5 年内的二手车销售价如下表:设计一种购买货车的方案,使5 年内用车的总费用最少。
选作:将其中所有的数据,包括售价、年份、各年份的费用和各年份二手车销售价等的数据改为任意值。
1.二分法:#include<stdio.h>#include<math.h>void main(){double x,x1=1,x2=3,f1,f2,f;f1=x1*x1*x1-3*x1-1;f2=x2*x2*x2-3*x2-1;if(f1*f2>0)printf("在此区间没有根!");else{do{x=(x1+x2)/2;f=x*x*x-3*x-1;if(f==0)break;else if(f1*f>0){x1=x;f1=f;}else{x2=x;}}while(fabs(x1-x2)>=0.000001);printf("近似值为:%.7f\n",x);printf("与理论值相差为:%.7f",x-1.8793852);}}牛顿迭代法:#include<stdio.h>#include<math.h>void main(){double f0,f1,x0,x1=2;do{x0=x1;f0=3*x0*x0-3;f1=x0*x0*x0-3*x0-1;x1=x0-f1/f0;}while(fabs(x1-x0)>=0.0000001);printf("近似值为:%.7f",x1);printf("与理论值相差: %.7f",x1-1.8793852); }2.#include<iostream>using namespace std;int main(){int N,i,j,k,l,n=0;3.源代码:#include <iostream>#include <vector>using namespace std;int pro[5] = { 3,5,10,16,21 };//货车保护费int sale[6] = { 0,17,15,7,4,2 };//二手车销售价格int minmoney = -65536;#define MAX 20int num[MAX] = { 1,2,3,4 };int n = 0;vector<vector<int>>ps;void solve(int n) {vector<vector<int>>ps1;vector<vector<int>>::iterator it;vector<int>s;ps.push_back(s);for (int i = 0; i < n; i++) {}}int main() {for (int i = 1; i<5; i++) {pro[i] += pro[i - 1];}vector<int>mi;solve(4);show();system("pause");return 0;}程序运行结果:。
【算法复习一】常见的算法策略汇总
【算法复习一】常见的算法策略汇总一,概述算法策略和算法是有区别的,它们是算法设计中的两个方面,算法策略是面向问题的,算法是面向实现的;但二者又是不可分的,首先是通过算法策略才找出解决问题的算法,其次对于用不同算法求解的问题算法策略是自然不同的。
二,算法策略1)递推策略:“递推法”和贪心算法一样也是由当前问题的逐步解决从而得到整个问题的解,只是依赖的是信息间本身的递推关系,每一步不需要策略参与到算法中,它们更多地用于计算。
2)递归策略:递归法是利用大问题与其子问题间的递归关系来解决问题的。
每次找出大问题与小的子问题之间的关系,直到小的子问题很容易解决,再由小的子问题的解导出大问题的解。
例如:汉诺塔问题3)穷举策略:对所有可能的解逐一尝试。
4)递归回溯策略:类似于穷举法的思想,递归回朔法通过递归尝试遍问题各个可能解的通路,发现此路不通时回朔到上一步继续尝试别的通路。
5)分治策略:求解的则是较复杂的问题,这类问题是可以被分解成独立的子问题来解决的,将两个或两个以上的独立子问题的解“合成”,就得到较大的子问题的解,最后合成为总问题的解。
(注意一定是可以分解成独立子问题,否则会重复计算公共子问题)6)动态规划策略:动态规划法与贪心法类似,要求问题具有最优子结构(即最优解包含子问题的最优解),是一种自底向上的求解思路,与递归正好相反,每次求解到一个阶段时,该阶段求解所依赖的子问题已经完全求解完毕,因此每一步的求解都是在直到全部所需信息的情况下进行的,因此可以得到全局最优解。
7)贪心策略:如果想要得到最优解,需要对问题性质有更严格的要求,除了要有最优子结构外,还要求问题具有贪婪选择性质。
具体来说就是:贪心是一种策略,即每一步都要选择当前看来最好的,做完此选择后便将问题化为一个(仅仅一个)子问题,这是一个顺序的求解过程,每一步都是单独考虑,只考虑局部最优,因为并没有完成对之后子问题的求解,所以贪心算法不能完成对整个解空间的搜索,因此通常不能得到最优解。
第四章1算法策略迭代算法
第四章1算法策略迭代算法迭代算法是一种通过重复应用一些过程或步骤来逐步逼近解的策略。
在计算机科学中,迭代算法是解决问题的一种常见方法,尤其在计算复杂度比较高的情况下,迭代算法可以提供一种有效的解决方案。
迭代算法的核心思想是将问题分解成一系列小的子问题,并通过重复执行一些步骤来逐渐逼近解。
每次迭代时,算法会根据上一次迭代的结果来更新当前的状态,然后继续下一次迭代。
这样的迭代过程会持续进行,直到达到一些停止条件为止。
迭代算法可以应用在各个领域的问题中,比如数值计算、优化问题、问题等。
下面将介绍一些常见的迭代算法。
1.迭代加深:这是一种在问题中应用的常见迭代算法。
它通过逐渐增加的深度来逼近解。
首先进行深度为1的,如果没有找到解,则增加深度,再次进行。
通过不断增加深度,直到找到解为止。
2.迭代法解线性方程组:线性方程组的解可以通过迭代算法逐步求得。
一种常见的迭代算法是雅可比迭代法,它通过不断迭代解方程组的近似解,直到满足特定的收敛准则为止。
3.迭代法求函数零点:对于给定的函数,通过迭代算法可以逐步逼近函数的零点。
其中,牛顿迭代法是一种常见的迭代算法,它通过使用函数的导数和当前函数值来逐步逼近零点。
除了上述几种常见的迭代算法,还有其他很多迭代算法方法,如迭代法解非线性方程组、最小二乘法、迭代法求特征值等。
迭代算法的优点是它可以解决很多复杂的问题,并且可以提供一种近似解。
此外,迭代算法通常比较灵活,可以根据实际情况进行调整。
迭代算法的缺点是它可能需要进行大量的迭代次数才能得到满意的结果,并且在一些情况下可能无法收敛到解。
总之,迭代算法是一种常见的算法策略,可以应用于很多领域的问题。
通过不断迭代,算法可以逐步逼近最优解或者满足特定的目标。
虽然迭代算法可能需要较长时间才能得到完美的解,但它是解决复杂问题的一种有效方法。
基础算法策略-枚举.
注意: 1. 加号与等号各自需要两根火柴棍 2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、 C>=0) 3. n根火柴棍必须全部用上
分析
1.
2.
3. 4.
5.
0~9的数字所用的火柴数:6,2,5,5,4,5,6,3,7,6 对于N<=24,去掉+,=,实际上数字只有20根火柴。 首先考虑解集合,因为最多为20根火柴组成数字: 不可能为10个1; 不可能8个1,1个4; 不可能为7个1,2个7或1个0; ….. C不会超过1000
【输入样例】 3 1 5 {共有3个嫌疑人,其中有1个人始终说假话,有5条证词} MIKE CHARLES 嫌疑人的名字(3个)
KATE
MIKE:I am guilty. MIKE:Today is Sunday. CHARLES:MIKE is guilty. KATE:I am guilty. KATE:How are you?? 【输出样例】
证词~(5条)
MIKE
分析
这道题的关键点是“如何能够快速正确实现出来” ,事 实上这道题对编码能力的要求要大于对算法本身的要求。 由于这道题的数据范围并不是很大,但需要进行“字符串 处理”这种比较麻烦的工作,因此在比赛时就可以采用效 率低一些的枚举算法来换取编码上的简单。
局部枚举
例题4:新年好
某城里有n个车站,m条双向公路连接其中的某 些车站。每两个车站最多用一条公路直接相连, 从任何一个车站出发都可以经过一条或多条公 路到达其他车站,但不同的路径需要花费的时 间可能不同。在一条路上花费的时间等于路径 上所有公路需要的时间之和。
佳佳的家在车站1,他有五个亲戚,分别住在 车站a,b,c,d,e。过年了,他需要从自己的家出 发,拜访每个亲戚(顺序任意),给他们送去 节日的祝福。怎样走,才需要最少的时间?
基本算法策略
2 算法的特性 解决一个问题的方法要称之为算法,即一个方法要成为程序 设计中所使用的算法,需要具备如下特性: 1,有穷性 例如,以下的计算公式不能称之为算法: S=1+2+3+4+…+100+101+…+1000+1001+…… 2,确定性 3,有零个或多个输入 4,有一个或多个输出 5, 可执行性 一个算法的合法与否,最直接的当然就是可以由计算机执行, 算法中描述的操作都可以通过计算机的运行来实现。
程序设计方法简述
3、程序测试
§ 目的 发现程序中的错误(Bug) § 程序错误 ◆语法错误(编译系统检查) ◆逻辑错误(编程人员检查) § 方法与技术 测试是以程序通过了编译,没有语法和连接错误为前提。在此基础上 运行一组数据,来检测程序的逻辑错误。这一组测试数据应是以“任 何程序都是有错误的”为前提精心设计出来的。它不仅应含有被测程 序各种情况下的代表性输入数据,还应包括程序执行这些数据后预期 的结果。 § 其他 著名计算机软件科学家E.W.Dijkstra曾断言:“程序测试只能证明错误 的存在,而不能证明错误的不存在”。可以证明,除了很小的程序外, 无论使用任何方法,要想做到彻底的测试,即发现程序中的所有错误, 是不现实的。 常见所谓“β版”商业软件,就是软件正式发行前的测试版本。
【讨论】
令z=100-x-y 1%)
只进行101×101= 10201 次运算(前者的
【例二】雨水淋湿了算术书的一道题,8个数字只 能看清3个,第一个数字虽然看不清,但可看出不 是1。编程求其余数字是什么? [ □×(□3+□)]2 = 8□□9 §分析 设分别用A、B、C、D、E五个变量表示自左到右五 个未知的数字。其中A的取值范围为2~9,其余取 值范围为0~9。条件表达式即为给定算式。
常见的算法设计策略
常见的算法设计策略常见的算法设计策略1.分治分治法的设计思想是,将一个难以直接解决的大问题,分割成k 个规模较小的子问题,这些子问题相互独立,且与原问题相同,然后各个击破,分而治之。
分治法常常与递归结合使用:通过反复应用分治,可以使子问题与原问题类型一致而规模不断缩小,最终使子问题缩小到很容易求出其解,由此自然导致递归算法。
根据分治法的分割原则,应把原问题分割成多少个子问题才比较适宜?每个子问题是否规模相同或怎样才为适当?这些问题很难给与肯定的回答。
但人们从大量实践中发现,在使用分治法时,最好均匀划分,且在很多问题中可以取k=2。
这种使子问题规模大致相等的做法源自一种平衡子问题的思想,它几乎总是比使子问题规模不等的做法好。
2.动态规划动态规划法与分治法类似,其基本思想也是将原问题分解成若干个子问题。
与分治法不同的是,其分解出的子问题往往不是相互独立的。
这种情况下若用分治法会对一些子问题进行多次求解,这显然是不必要的。
动态规划法在求解过程中把所有已解决的子问题的答案保存起来,从而避免对子问题重复求解。
动态规划常用于解决最优化问题。
对一个最优化问题可否应用动态规划法,取决于该问题是否具有如下两个性质:1.最优子结构性质当问题的最优解包含其子问题的最优解时,称该问题具有最优子结构性质。
要证明原问题具有最优子结构性质,通常采用反证法。
假设由问题的最优解导出的子问题的解不是最优的,然后再设法说明在该假设下可构造出比原问题的最优解更好的解,从而导致矛盾。
2.子问题重叠性质子问题重叠性质是指由原问题分解出的子问题不是相互独立的,存在重叠现象。
用动态规划法解题过程中,应当先找出最优解的结构特征,即原问题的最优解与其子问题的最优解的关联。
然后有如下两种程序设计方法:1.自底向上递归法利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解。
2.自顶向下递归法(即备忘录法)利用问题的最优子结构性质,用与直接递归法相同的控制结构自顶向下地进行递归求解。
大学计算机基础-04-算法分析与设
4.1 算法的基本概念
用流程图表示算法直观形象,比较清楚地显示出各个框之间的 逻辑关系。但这种流程图占用篇幅较多,尤其当算法比较复杂时, 画流程图既费时又不方便。在结构化程序设计方法推广之后,经常 采用N-S结构化流程图代替传统的流程图。 N-S流程图是一种适于结构化程序设计的流程图。在N-S流程图 中,完全去掉了带箭头的流程线,全部算法写在一个矩形框内,在 该框内可以包含其它从属于它的框,或者说,由一些基本的框组成 一个大的框。
4.1 算法的基本概念
一个算法必须具备以下性质:
• 确定性。算法中每一个步骤都必须是确切定义的,不能产生二义性。 • 可行性。算法必须是由一系列具体步骤组成的,并且每一步都能被计算机所 理解和执行。 • 有穷性。一个算法必须在执行有穷步后结束,每一步必须在有穷的时间内完 成。 • 输入。一个算法可以有零个或多个输入,这取决于算法要实现的功能。 • 输出。一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有 输出的算法是毫无意义的。
4.1 算法的基本概念
对算法的学习包括5个方面的内容: • 设计算法 • 表示算法 • 确认算法 • 分析算法 • 验证算法
4.1 算法的基本概念
4.1.2 设计算法原则和过程 对于一个特定问题的算法在大部分情况下都不是唯一的。也就 是说,同一个问题,可以有多种解决问题的算法,而对于特定的问 题、特定的约束条件,相对好的算法还是存在的。因此,在特定问 题、特定的条件下,选择合适的算法,会对解决问题有很大帮助; 否则前人的智慧我们不能借鉴,凡事就都得自己从头研究了,这就 是所谓的要去“发明轮子(Invent the wheel)”。
4.1 算法的基本概念
对于这四层含义,第①层次要求最低,因为仅仅没有语法错误 实在谈不上是好算法。而第④层次是最困难的,我们几乎不可能逐 一验证所有的输入都得到正确的结果。 因此,算法的正确性在大部分情况下都不可能用程序来证明, 而是用数学方法证明的。证明一个复杂算法在所有层次上都是正确 的,代价非常昂贵。所以一般情况下,我们把层次③作为一个算法 是否正确的标准。
算法优化策略
算法优化策略提倡算法多样化绝不是算法在形式上越多越好,其更深层次的目的是培养学生的创新意识和自我价值观念。
因此,在算法多样化的基础上进行算法的优化教学尤为重要。
一、算法优化需要教师的引导课程标准指出:“教师不要急于评价各种算法,应引导学生通过比较各种算法的特点,选择适合自己的方法。
”每一个学生的知识背景和理解程度各不相同的,对优化的感悟也存在着差异性。
有的学生能在交流中很快地感悟到优化的算法,并对自己的算法及时进行修正与整合。
有的学生却迟迟感悟不到,这时,教师绝对不能把自己的想法和观点强加于学生。
应尊重学生的认知规律,先创设一定的教学情境引导学生对各种算法进行归纳整理、分析比较,不断地去理解、去感悟。
如,计算9加几时,教师创设情境,得出算式9+5后,学生想出了多种算法:(1)从9往后数,再数5(4)10+Array 4=14,(2)、(320以内如,(1)把9分成3)在35;(5接着,我设计了这样一个练习:让学生分别计算3+9、23+9、43+9、73+9,然后比一比,说一说,看看这些算式之间的联有什么异同,从中你发现了什么。
学生在观察、比较、讨论、交流中发现每道题里面都要先算3+9,而23+9,43+9,73+9,只要再算20+12,40+12,70+12就可以了。
在这个过程中,他们会自觉地对解题方法进行回顾、反思、总结、比较、自我调节。
这个过程本身也是一个思维不断深入的过程。
在进行“多中选优、择优而用”的活动中,学生学会了选择,不但增强了具体问题具体分析的意识,也培养了良好的思维品质。
教学中,教师有责任引导学生去比较、去评价,并让他们掌握那些公认的更好、更一般的算法,以便举一反三,触类旁通。
三、算法优化应尊重个性、应人而异算法优化的过程是一个促进学生学会反思、自我完善的过程。
教师应把选择判断的主动权放给学生,引导学生自主分析、讨论、比较,从而“悟”出属于自己的最佳方法。
教师在评价算法时,不要讲“优点”,而要讲“特点”,把优点让给学生自己去感悟,为学生多留一些思考的空间,让所有学生都能在原有基础上得到发展,这才达到了优化算法的目的。
第四章3算法策略剖析
else if (dr >= tr + s && dc < tc + s) //残缺方格位于覆盖左下象限 { Cover(tr+s, tc, dr, dc, s); Board[tr + s - 1][tc + s - 1] = t; // 覆盖3号三格板 Board[tr + s - 1][tc + s] = t; Board[tr + s][tc + s] = t; Cover (tr, tc, tr+s-1, tc+s-1, s); //覆盖其余部分 Cover (tr, tc+s, tr+s-1, tc+s, s); Cover(tr+s, tc+s, tr+s, tc+s, s); }
分治法的一般的算法设计模式如下:
Divide-and-Conquer(int n)
/n为问题规模/
{ if (n≤n0) { 解子rn(子问题的解);}
for (i=1 ;i<=k;i++)
/分解为较小子问题p1,p2,……pk/
yi=Divide-and-Conquer(|Pi|); /递归解决Pi/
算法如下:
图4-9 一个4*4的残缺棋盘及其解
int amount=0; main( )
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
①号
②号 四种三格板
③号
④号
这样的棋盘我们称作“三格板”,残缺棋盘问题就是要用这 四种三格板覆盖更大的残缺棋盘。在此覆盖中要求: 1)两个三格板不能重叠 2)三格板不能覆盖残缺方格,但必须覆盖其他所有的方格 在这种限制条件下,所需要的三格板总数为(2k×2k -1 )/3。
算法设计1:下面用分而治之方法解决残缺棋盘问题。 1)问题分解过程如下: 以k=2时的问题为例,用二分法进行分解,得到的是如下图48,用双线划分的四个k=1的棋盘。但要注意这四个棋盘,并 不都是与原问题相似且独立的子问题。因为当如图4-8中的 残缺方格在左上部时,第1个子问题与原问题相似,而右上 角、左下角和右下角三个子棋盘(也就是图中标识为2、3、 4号子棋盘),并不是原问题的相似子问题,自然也就不能 独立求解了。当使用一个①号三格板(图中阴影)覆盖2、3、 4号三个子棋盘的各一个方格后,如4-8右图所示,我们把覆 盖后的方格,也看作是残缺方格(称为“伪”残缺方格), 这时的2、3、4号子问题就是独立且与原问题相似的子问题 了。
一个4*4的残缺棋盘
从以上例子还可以发现,当残缺方格在第1个子棋盘,用①号三 格板覆盖其余三个子棋盘的交界方格,可以使另外三个子棋 盘转化为独立子问题;同样地(如下图4-9所示),当残缺方 格在第2个子棋盘时,则首先用②号三格板进行棋盘覆盖,当 残缺方格在第3个子棋盘时,则首先用③号三格板进行棋盘覆 盖,当残缺方格在第4个子棋盘时,则首先用④号三格板进行 棋盘覆盖,这样就使另外三个子棋盘转化为独立子问题。
多数问题需要所有子问题的解,并由子问题的解,使用恰 当的方法合并成为整个问题的解,比如合并排序,就是不断将 子问题中已排好序的解合并成较大规模的有序子集。
• 适合用分治法策略的问题 当求解一个输入规模为n且取值又相当大的问题时,用蛮 力策略效率一般得不到保证。若问题能满足以下几个条件, 就能用分治法来提高解决问题的效率。 1)能将这n个数据分解成k个不同子集合,且得到k个子集 合是可以独立求解的子问题,其中1<k≤n; 2)分解所得到的子问题与原问题具有相似的结构,便于 利用递归或循环机制;
一个4*4的残缺棋盘及其解
算法如下: int amount=0; main( ) { int size=1,x,y; input(k); for (i=1;i<=k;i++) size=size*2; print(“input incomplete pane ”); input(x,y); Cover(0, 0, x, y, size); }
Cover(int tr, int tc, int dr, int dc, int size) { if (size<2) return; int t = amount ++, // 所使用的三格板的数目 s=size/2; // 子问题棋盘大小 if (dr < tr + s && dc < tc + s) / /残缺方格位于左上棋盘 {Cover ( tr, tc, dr, dc, s); Board[tr + s - 1][tc + s] = t; // 覆盖1号三格板 Board[tr + s][tc + s - 1] = t; Board[tr + s][tc + s] = t; Cover (tr, tc+s, tr+s-1, tc+s, s); // 覆盖其余部分 Cover(tr+s, tc, tr+s, tc+s-1, s); Cover(tr+s, tc+s, tr+s, tc+s, s); }
四、合并分类(归并排序)
先看插入排序: Void inபைடு நூலகம்ertsort(int a[ ],n) { //将数组a中的n个元素按非降序排列 a[0]=-32768;
for (j=2;j<=n;j++)
{item=a[j]; i=j-1; while(item<a[i]) {a[i+1]=a[i];i=i-1;} a[i+1] =item;
如下图4-9:
图4-9
其它4*4的残缺棋盘
同样地k=1,2,3,4……都是如此,k=1为停止条件。
2)棋盘的识别 棋盘的规模是一个必要的信息,有了这个信息,只要知道其左上 角的左上角方格所在行、列就可以唯一确定一个棋盘了,残 缺方格或“伪”残缺方格直接用行、列号记录。 • tr 棋盘中左上角方格所在行。 • tc 棋盘中左上角方格所在列。 • dr 残缺方块所在行。 • dl 残缺方块所在列。 • size 棋盘的行数或列数。 数据结构设计:用二维数组board[ ][ ],模拟棋盘。覆盖 残缺棋盘所需要的三格板数目为:( size2 -1 ) / 3 将这些三格板编号为1到( s i z e2-1 ) / 3。则将残缺棋 盘三格板编号的存储在数组board[ ][ ]的对应位置中,这 样输出数组内容就是问题的解。结合图4-9,理解算法。
else if (dr >= tr + s && dc >= tc + s)
限
// 残缺方格位于右下象
{Cover(tr+s, tc+s, dr, dc, s); Board[tr + s - 1][tc + s - 1] = t; // 覆盖4号三格板 Board[tr + s - 1][tc + s] = t; Board[tr + s][tc + s - 1] = t; Cover (tr, tc, tr+s-1, tc+s-1, s); //覆盖其余部分 Cover (tr, tc+s, tr+s-1, tc+s, s); Cover(tr+s, tc, tr+s, tc+s-1, s); } } 算法分析:因为要覆盖 void OutputBoard(int size) (size2 -1)/ 3个三格板, { for (int i = 0; i < size; i++) 所以算法的时间复杂性 为O(size2)。 { for (int j = 0; j < size; j++) print( Board[i][j]); print(“换行符”); } }
最好情况(递增):n-1
最坏情况(递减):2(n-1) 平均情况:3(n-1)/2
算法3:递归求取最大和最小元素
float a[n]; maxmin(int i, int j ,float &fmax, float &fmin) { int mid; float lmax, lmin, rmax, rmin; if(i=j) {fmax= a[i]; fmin=a[i];} else if (i=j-1) if(a[i]<a[j]) { fmax=a[j];fmin=a[i];} else {fmax=a[i]; fmin=a[j];} else { mid=(i+j)/2; maxmin(i,mid,lmax,lmin); maxmin(mid+1,j,rmax,rmin); if(lmax>rmax) fmax=lmax; else fmax=rmax; if(lmin>rmin) fmin=rmin; else fmin=lmin; } }
max=a[i]; min=a[i];
}
}
平均比较次数:2*(n-1)
算法2: maxmin( float a[],int n) { max==min=a[1]; for(i=2 i<=n i++ ) if(max<a[i]) max=a[i]; else if(min>a[i]) } min=a[i];
•设计模式:
Divide-and-Conquer(int n)
{ if(n≤n0) { 解子问题;
//n为问题规模
//n0 为可解子问题的规模
return(子问题的解); } for(i=1 ;i<=k;i++) //分解为较小子问题p1,p2,……pk yi=Divide-and-Conquer(|Pi|); //递归解决Pi T=MERGE(y1,y2,...,yk); return(T); //合并子问题
1)分解:将原问题分解为若干个规模较小,相互独立,与原问 题形式相同的子问题; 2)解决:若子问题规模较小而容易被解决则直接解,否则再继 续分解为更小的子问题,直到容易解决; 3)合并:将已求解的各个子问题的解,逐步合并为原问题的解。
有时问题分解后,不必求解所有的子问题,也就不必作第三步 的操作。比如折半查找,在判别出问题的解在某一个子问题中 后,其它的子问题就不必求解了,问题的解就是最后(最小) 的子问题的解。分治法的这类应用,又称为“减治法”。
}
}
再看归并排序
基本思想:将集合a分成两个集子合,递归地对每个子 集合单独分类,然后将已排序的两个子集合归并成一 个集合
void mergesort(int a[N],int low,int high) { int b[N]; if(low<high) m=(low+high)/2;
mergesort(a,low,m);
算法分析: 递归关系式(比较次数):
当n是2的幂时,即对于这个某个正整数k,n=2k,有
可以证明,任何以元素 比较为基础的找最大和 最小元素的算法,其元 素比较下界均为 次。 因此,过程MAXMIN在这 种意义上是最优的。
三、二分法不相似情况
【例】残缺棋盘 残缺棋盘是一个有2k×2k (k≥1)个方格的棋盘,其中恰有 一个方格残缺。图4-7给出k=1时各种可能的残缺棋盘,其 中残缺的方格用阴影表示。