算法分析大作业
算法分析与设计大作业

算法分析与设计大作业摘要:本文以算法分析与设计为主题,对算法的概念、分析和设计进行了探讨。
首先介绍了算法的概念和基本特征,其次分析了算法的效率和复杂度,并介绍了常用的算法复杂度表示方法。
然后,通过实例分析了几种常用的排序算法的性能与复杂度,并对它们进行了比较。
最后,总结了算法分析与设计的重要性,并提出了进一步研究的方向。
一、引言随着计算机技术的快速发展,算法分析与设计成为计算机领域中的重要研究方向。
算法是指解决特定问题的具体步骤和方法,是计算机科学的核心和基础。
算法的效率和复杂度对计算机的性能和运行时间有着直接的影响,因此算法的分析和设计非常重要。
二、算法的概念和特征算法是指在有限的时间内解决特定问题的一种方法。
它具有以下特征:输入、输出、确定性、有穷性和可行性。
输入是指算法接受的问题的数据或信息,输出是指算法求解得到的问题的解。
确定性是指算法在任何情况下都能够得到相同的结果。
有穷性是指算法在执行有限的步骤后能够终止。
可行性是指算法的每一步都是可行的,即能够被计算机执行。
三、算法的效率和复杂度算法的效率是指算法解决问题所需要的时间和空间资源的多少。
算法的复杂度是用来描述算法执行过程中所需要的资源的多少。
常用的算法复杂度表示方法有时间复杂度和空间复杂度。
时间复杂度表示算法的执行时间与输入规模之间的关系,用大写O表示。
空间复杂度表示算法所需的空间资源与输入规模之间的关系,用大写S表示。
四、常用的排序算法及性能与复杂度分析1.插入排序插入排序是一种简单直观的排序算法。
它的基本思想是将未排序的元素逐个插入到已排序的序列中。
插入的过程中,需要比较和移动元素的次数与未排序序列中的元素个数相关,因此时间复杂度为O(n^2)。
空间复杂度为O(1)。
2.冒泡排序冒泡排序是一种重复比较相邻元素并交换位置的排序算法。
它的基本思想是两两比较相邻元素,如果顺序错误则交换位置。
冒泡的过程中,需要进行n-1次的比较和交换操作,因此时间复杂度为O(n^2)。
算法设计与分析报告大作业

算法分析与设计大作业班级: 12信科姓名:郭倩南学号: 1242155105完成日期: 2015-6-4指导教师:陈平序号选定题目所用算法设计技术1数字三角形问题动态规划2集合划分问题分治法回溯法3求子集问题评分:大作业报告1、数字三角形问题一、问题描述对于给定的由n行数字组成的数字三角形,计算从三角形的底至顶的路径经过的数字和的最大值。
如:73 88 1 02 7 4 44 5 2 6 5二、实验内容与实验步骤实验内容:输入数据的第1 行是数字三角形的行数n,1<=n<=100。
接下来n行是数字三角形各行中的数字。
所有数字在0..99之间实验步骤:1、首先证明该问题满足最优化原理最优化原理:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。
简而言之,一个最优化策略的子策略总是最优的。
2、建立动态规划函数3、填表三、实验环境Window7系统,vc++6.0软件四、问题分析由观察数字三角形可知,从数字三角形的顶层出发,下一层选择向左还是向右取决于两个4层数字三角形的最大数字和,而对于第四层的决定取决于第三层的最大数字和,依次类推,可知该问题是多阶段决策最优化问题,并且划分出来的子问题是相互重叠的,所以该问题采用动态规划法解决动态规划:与分治法相似,把问题分解按层次分成子问题,直到可以直接求解的子问题,然后一级一级地向上求解。
与分治法的出别在于:动态规划适用有许多重复子问题出现的问题,它保存已求出问题的解。
73 8 3 88 1 0 8 1 1 02 7 4 4 2 7 4 7 4 4 4 5 2 6 5 4 5 2 6 5 2 6 5一个五层数字三角形子问题〔1〕子问题〔2〕五、问题解决〔1〕根据对问题的分析,写出解决方法。
1、证明:S,S1,S2,..Sn,t是从S到t的一条数字和最大的路径,从源点S开始,设从S到下一段的顶点S1已经求出,如此问题转化为求从S1到t的数字和最大的路径,显然S1,S2,...Sn,t一定构成一条从S1到t的数字和最大值的路径,如假如不然,设S1,r1,r2,....rq,t是一条数字和最大的路径,如此S,S1,r1,r2,....rq,t的路径经过数字和的最大值比S,S1,S2,...Sn,t的路径数字和更大,从而导致矛盾,所以数字三角形问题满足最优性原理。
算法设计与分析课程大作业

题目作业调度问题及算法分析学院名称:计算机与信息工程学院专业名称:计算机科学与技术目录《算法设计与分析》课程大作业 (1)一.动态规划算法解决流水作业调度 (3)1、问题描述 (3)2、算法分析 (3)3. 算法的描述 (4)4、部分算法实现 (5)5. 运行结果 (6)6、时空效率分析 (6)二.贪心算法解多机调度问题 (6)1、问题描述 (6)2、算法分析 (7)3.部分算法实现 (7)4.计算复杂性分析 (8)5. 运行结果 (9)三.回溯法解决批作业调度问题 (9)1.问题描述 (9)2.算法思想 (10)3. 部分算法实现 (11)4.运行结果 (12)5.时间复杂性分析 (12)四.作业调度算法比较 (12)五.课程学习总结 (13)摘要:在现代企业中,作业调度已成为提高资源利用率、从而提高企业运行效益的关键环节之一。
把各个作业分配到车间现有的设备上,并确定它们的先后次序,这是一项复杂的工作本文就作业调度排序问题进行了研究,通过对几个经典作业调度算法的分析讨论,总结了各个算法对作业调度的求解过程,并给出了每个算法的复杂度及性能分析。
关键词:作业调度;动态规划;贪心算法;回溯法;一.动态规划算法解决流水作业调度1、问题描述给定n 个作业,每个作业有两道工序,分别在两台机器上处理。
一台机器一次只能处理一道工序,并且一道工序一旦开始就必须进行下去直到完成。
一个作业只有在机器1上的处理完成以后才能由机器2处理。
假设已知作业i 在机器j 上需要的处理时间为t[i,j]。
流水作业调度问题就是要求确定一个作业的处理顺序使得尽快完成这n 个作业。
2、算法分析直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少。
在一般情况下,机器M2上会有机器空闲和作业积压2种情况。
在一般情况下,机器M1开始加工S 中作业时,机器M2还在加工其他作业,要等时间t 后才可利用。
将这种情况下完成S 中作业所需的最短时间记为T(S,t)。
Linux大作业的算法分析怎么写

Linux大作业的算法分析怎么写Linux大作业分析框架1、以算法输入规模n作为参数进行分析算法效率2、时间复杂度:找出基本操作O(1),再计算它的运行次数(忽略乘法常量,仅关注增长次数)3、增长次数:log2n4、最差、平均和最佳效率均是指输入规模为n时候的效率(平均效率可以引用已知的推到结果)主要概括分析框架:1、算法的时间效率和空间效率都用输入规模的函数进行度量。
2、用算法的基本操作的执行次数来度量时间效率,用算法消耗的额外单位的数量来度量空间单位3、在输入规模相同的情况下,有写算法的效率会有显著的差异,对于这类算法需要分析最差、平均和最佳效率4、框架主要关心:输入规模趋向于无限大的情况下它的效率问题渐近符号和基本效率类型1、O(g(n))是增长次数&lt;=c*g(n)的函数集合,上阶2、Ω(g(n))是增长次数&gt;=c*g(n)的函数集合,下阶3、θ(g(n))是增长次数=c*g(n)的函数集合,同阶可以利用极限进行比较增长次数(洛必达法则)算法整体效率是由具有较大增长次数的部分所决定的。
非递归问题的数学分析的通用方案1、决定哪个参数表示输入规模的度量标准2、找出算法的基本操作3、检查基本操作的执行次数是否只依赖于输入规模,如果它还依赖于一些其他的特性(例如:元素在数组中的位置等)则分析最差、平均和最佳效率4、建立一个算法基本操作执行次数的求和表达式(有可能是递推表达式)5、利用求和运算的标准运算或者法则来建立一个操作次数的闭合公式,或者至少确定它的增长次数递归问题的数学分析的通用方案1、决定哪个参数表示输入规模的度量标准2、找出算法的基本操作3、检查基本操作的执行次数是否只依赖于输入规模,如果它还依赖于一些其他的特性(例如:元素在数组中的位置等)则分析最差、平均和最佳效率4、对于算法基本操作执行次数,建立一个递推关系以及相应的初始条件。
5、解这个递推式,或者至少确定它的增长次数。
算法设计与分析大作业评分标准

课号:____CK5J08A ___ 课名:_____算法设计与分析______教师: ________________期末大作业要求:在以下几种方式中任选一种一.算法实际应用题任务要求:1.完成一个有一定实用性的程序,其中包含稍复杂的算法模块,算法输入和输出必须显示在图形界面上,最好能把算法运行过程展现在图形界面上。
2.撰写算法设计报告,描述算法设计流程,分析算法效率。
3.进行答辩。
评分标准:1.图形界面的操作方便性与对算法的展现程度(30分)2.算法的复杂程度和算法效率和实用性(30分)3.算法设计流程的解释的清晰度和算法效率分析的准确度(30分)4.答辩10分,采用教师提问学生回答和解释的形式,学生若不能自圆其说、对自己设计的算法流程也讲不清楚,则判定为抄袭,整个大作业为0分。
参考题目:1.算242.倒油3.趣味算式4.马步问题5.单源最短路径6.最小生成树7.工作分配8.2*2*2魔方9.长江游艇10.推箱子11.华容道12.文件搜索13.………..二.ACM算法设计题任务要求:1.完成2道及2道以上ACM算法设计题,题目由教师给定并公布在OJ系统中,学生限定时间内(2个小时),在其中选做2题以上,正确性也由OJ系统判定,并参照OJ系统的标准,形成排名。
完成数量不到2题的,不管排名如何,整个大作业都判定为不及格。
2.为所完成的每道题目撰写解题报告,描述设计思路与流程,分析课号:____CK5J08A ___ 课名:_____算法设计与分析______教师: ________________程序的时空效率。
评分标准:1.算法设计能力(60分),主要根据OJ系统中的排名来评定,部分提交的题目有抄袭嫌疑的学生,教师对其进行质询答辩,采用问答形式,学生若对其提交正确的任何题目,无法通过质询答辩,则判定为抄袭,整个大作业为0分。
2.算法表述与分析能力(40分),根据提交的解题报告中,对算法流程的描述的清晰程度,对算法时空效率的分析的准确程度,进行评定。
算法设计与分析大作业报告

《算法设计与分析大作业报告》班级:学号:姓名:分治法大作业报告问题陈述:编程实现归并排序算法和快速排序算法,输出排序结果。
输入10组相同的数据,验证排序结果和完成排序的比较次数。
分治法基本思想:分治法的基本思想是将问题分解成若干个子问题,然后求解子问题。
子问题较原问题要容易些,先得出子问题的解,由此得出原问题的解,这就是所谓“分而治之”的思想。
算法描述:当要求解一个输入规模为n,且n的取值相当大的问题时,如果问题可以分成k个不同子集合,得到k个不同的可独立求解的子问题,其中1<k≤n,而且子问题与原问题性质相同,原问题的解可由这些子问题的解合并得出。
那末,对于这类问题分治法是十分有效的。
本实验就是通过归并排序和快速排序来体现分治的思想。
1.归并排序的思想:将A(1),……,A(N)分成两个集合,对每个集合单独分类,然后将已分类的两个序列归并成一个含N个元素分好类的元素2.快速排序的思想:选取A的某个元素做为划分元素,然后将其他元素重新排列,使在划分元素以前出现的元素都小于或等于它,在划分元素之后出现的划分元素都大于等于它。
程序代码:#include <stdio.h>#include <time.h>#include <stdlib.h>void MergeSort(int *data,int x,int y,int *temp){ int p,q,m,i=x;if (y-x>1){m = x+(y-x)/2;p = x;q = m;MergeSort(data,x,m,temp);MergeSort(data,m,y,temp);while(p<m||q<y){if (q>=y||(p<m&&data[p]<data[q])){temp[i++] = data[p++];}else{temp[i++] = data[q++];}}for(i=x;i<y;i++)data[i] = temp[i]; }}void HoareSort(int *data,int x,int y){int p=x,q=y-1,temp;while(p<q) {while (q>p&&data[q]>=data[p])q--;if (q>p){temp = data[p],data[p] = data[q],data[q] =temp;p++;}while(q>p&&data[p]<=data[q])p++;if (p<q){temp = data[p],data[p] = data[q],data[q] =temp;q--;}if (p==q) {HoareSort(data,x,p);HoareSort(data,p+1,y);}}}int main(){int data[10],i;int temp[10];srand(time(NULL));for (i=0;i<10;i++){ data[i] = rand()%100; }printf("未排序排序的数据为:\n");for (i=0;i<10;i++){printf("%d ",data[i]);}printf("\n");printf("归并排序的顺序为: \n");MergeSort(data,0,10,temp);for (i=0;i<10;i++){printf("%d ",data[i]); }printf("\n");printf("快速排序的顺序为: \n");HoareSort(data,0,10);for (i=0;i<10;i++){printf("%d ",data[i]);}printf("\n");return 0;}运行结果:结论分析:归并排序和快速排序都是递归排序,但是归并排序是稳定的排序方法,快速排序是不稳定的排序方法。
【图文】算法分析与设计大作业

算法理论、教改类题目学习大量相关算法(程序),总结出对应方法的一些特点,将其写成论文形式,并以足够的例子作为佐证。
24.论分治法、动态规划、贪心法的区别 25.论递归程序向非递归程序的转换 26.论应用型本科院校算法课程的教学目标和教学方法 27.论二叉树在计算机科学与技术中的应用 28.数据库索引的算法解释 29.论贪心法的适用范围 30.解空间搜索方法的选择依据 31.分治法算法分析综述
算法应用、算法研究类题目查阅大量相关资料,对相关内容给出初步的结果。
31.基于UCCI的中国象棋对弈引擎开发技术研究 32.五子棋对弈关键技术研究33.黑白棋对弈关键技术研究 34.数独初始局面生成算法研究 35.支持按文件名搜索的索引构造技术研究 36.通用回溯算法演示系统设计 37.通用分支限界算法演示系统设计 38.通用排序算法演示系统设计 39.通用动态规划算法演示系统设计
40.论文阅读和翻译类题目• 给出一个英文文献,用准确的语言将其翻译为中文,不需要逐字逐句翻译,但主要观点、算法思想和算法过程表述清楚、准确、充分。
格式要求• 论文正文中不得出现大段代码(超过10行)• 标题样式需规范• 参考文献不低于10篇,参考文献格式和标注位置须规范。
算法分析与设计作业

最接近点对问题问题此问题分为一维,二维,三维的情况1. 一维: 给定直线上n 个点,找其中一对点,使得在n 个点组成的所有点对中,该点对间的距离最小,这个问题比较简单,是引出二维解法的一个引子,因为一维的直线上的点,相邻点的距离肯定小于相隔的点的距离,只需要考虑相邻点即可。
2. 二维:给定平面上n 个点,找其中一对点,使得在n 个点组成的所有点对中,该点对间的距离最小,这是我们这一问题的重点3. 三维:给定空间上n 个点,找其中一对点,使得在n 个点组成的所有点对中,该点对间的距离最小,此问题是二维的解法的复杂化,具体可以在飞机航线等问题上运用,但在此不多做介绍。
基本思想由于该问题的基本解法是去考察每个点和其他所有点的距离。
因此它的时间复杂度是2()O n ,这样做的效率太低,我们就要去寻找一个更高效的办法:分治法。
1. 因二维的情况太过复杂,先考虑一维的情况中,可以用分治法对其进行分部计算: 把直线分成两部分, 1s 2s ,分别求出其最接近点的距离1d 2d 。
但分割开的地方的两点距离可能小于这两个值,这三个值进行比较之后,得到最后结果。
2. 鉴于此,二维的也可以用此方法进行计算:把待计算的点s 分成两部分1s 2s ,分别求出其最接近点的距离1d 2d 。
但1d 2d 最小的未必是s 中的最小距离d ,它有可能是1s 中的一个点和2s 中的一个点组成的最接近点对。
所以还要考虑1s 中的所有点到2s 中的每一个点的距离,一一比较之后得出一个最小值,再和1d 2d 比较,这就得出了最后结果。
3. 接下来是具体算法实现的步骤:1. 把待计算的点s 分成两部分1s 2s :重要的如何去划分,这里采用在二维平面上的中线(用横坐标的最小值加上最大值的平均数)来划分。
2. 分别求出其最接近点的距离1d 2d :这可以用一个递归来完成。
3. 计算1s 中的所有点到2s 中的每一个点的距离:这个问题是此问题的关键。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法分析大作业动态规划方法解乘法表问题和汽车加油行驶问题目录1.动态规划解乘法表问题1.1问题描述------1.2算法设计思想------1.3设计方法------1.4源代码------1.5最终结果------2.动态规划解汽车加油行驶问题2.1问题描述------2.2算法设计思想------2.3设计方法------2.4源代码------2.5最终结果------3.总结1.动态规划解决乘法表问题1.1问题描述定义于字母表∑{a,b,c)上的乘法表如表所示:依此乘法表,对任一定义于∑上的字符串,适当加括号表达式后得到一个表达式。
例如,对于字符串x=bbbba,它的一个加括号表达式为(b(bb))(ba)。
依乘法表,该表达式的值为a。
试设计一个动态规划算法,对任一定义于∑上的字符串x=x1x2…xn,计算有多少种不同的加括号方式,使由x导出的加括号表达式的值为a。
1.2算法设计思想设常量a,b,c 分别为 1, 2 ,3 。
n 为字符串的长度。
设字符串的第 i 到第 j 位乘积为 a 的加括号法有result[i][j][a] 种,字符串的第 i 到第 j 位乘积为 b 的加括号法有result[i][j][b] 种,字符串的第 i 到第 j 位乘积为 c 的加括号法有result[i][j][c] 种。
则原问题的解是:result[i][n][a] 。
设 k 为 i 到 j 中的某一个字符,则对于 k 从 i 到 j :result[i][j][a] += result[i][k][a] * result[k + 1][j][c] + result[i][k][b] * result[k + 1][j][c] + result[i][k][c] * result[k + 1][j][a];result[i][j][b] += result[i][k][a] * result[k + 1][j][a] + result[i][k][a] * result[k + 1][j][b] + result[i][k][b] * result[k + 1][j][b];result[i][j][c] += result[i][k][b] * result[k + 1][j][a] + result[i][k][c] * result[k + 1][j][b] + result[i][k][c] * result[k + 1][j][c];输入:输入一个以a,b,c组成的任意一个字符串。
输出:计算出的加括号方式数。
1.3设计方法乘法表问题直观理解就是通过加括号使得最终运算结果为a,该问题与矩阵连乘问题类似,矩阵连乘是每一次加括号选择运算量最小的,写成数学表达式有:而乘法表问题则是计算所有加括号运算结果为a的情况数,并不要求输出加括号方式。
那么可以从乘法的最小单元两个符号相乘的所有可能开始,接着在两个符号相乘的基础上计算三个符号相乘的所有可能。
直到计算N长度的符号1-N的所有可能。
可以定义一个三维数组a[n][n][3],n为输入字符串的长度,a[i][j][0]为从字符串中第i个元素到第j个元素的子串表达式值为a的加括号方式数,a[i][j][1]为从字符串中第i个元素到第j个元素的子串表达式值为b的加括号方式数,a[i][j][2]为从字符串中第i个元素到第j个元素的子串表达式值为c的加括号方式数。
由乘法表的定义则可知啊a[i][j][0]=(对k求和,k从i到j-1)a[i][k][0]*a[i][k+1][2]+a[i][k][1]*a[i][k+1][2]+a[i][k][2]*a[i][k+1][1];同理可得到a[i][j][1]和a[i][j][2]。
同时由上面的表达式可知,要计算a[i][j][],需先计算a[i][k] []和a[i][k+1][],这里k从i到j-1,故a[i][j][]可采取如下的计算次序1.4源代码#include "iostream"#include "algorithm"#include "fstream"using namespace std;/*f[i][j][0] 表示在ch[i]~ch[j]之间以某种方式加括号后,结果为af[i][j][1] 表示在ch[i]~ch[j]之间以某种方式加括号后,结果为bf[i][j][2] 表示在ch[i]~ch[j]之间以某种方式加括号后,结果为ca = a*c || b*c || c*ab = a*a || a*b || b*bc = b*a || c*b || c*c */int f[50][50][3];char chars[3] = {'a', 'b', 'c'};int mul(int n, char ch[]){for(int i=0; i<n; i++)for(int k=0; k<3; k++)f[i][i][k] = (ch[i] == chars[k] ? 1: 0);/*a = a*c || b*c || c*ab = a*a || a*b || b*bc = b*a || c*b || c*c*/for(int r=1; r<n; r++) //规模for(i=0; i<n-r; i++) //区间左端点{int j = i + r; //区间右端点for(int k=i; k<j; k++) //断点{f[i][j][0] += f[i][k][0]*f[k+1][j][2] + f[i][k][1]*f[k+1][j][2] + f[i][k][2]*f[k+1][j][0];f[i][j][1] += f[i][k][0]*f[k+1][j][0] + f[i][k][0]*f[k+1][j][1] + f[i][k][1]*f[k+1][j][1];f[i][j][2] += f[i][k][1]*f[k+1][j][0] + f[i][k][2]*f[k+1][j][1] + f[i][k][2]*f[k+1][j][2];}}return f[0][n-1][0];}int main(){ifstream fin("mul.txt");cout << "输入字符串:";char ch[100];fin >> ch; cout << ch;int n = strlen(ch);cout << "\n结果为a的加括号方式为:" << mul(n, ch) << endl;fin.close();return 0;}1.5最终结果2.动态规划解决汽车加油行驶问题2.1问题描述给定一个N*N的方形网络,设其左上角为起点○,坐标为(1,1),X轴向右为正,Y轴向下为正,每个方格边长为1。
一辆汽车从起点○出发驶向右下角终点,其坐标为(M,N)。
在若干网格交叉点处,设置了油库,可供汽车在行驶途中,可供汽车在行驶途中加油。
汽车在行驶过程中应遵守如下规则:(1)汽车只能沿网格边行驶,装满油后能行驶K条网格边。
出发时汽车已装满油,在起点与终点处不设油库。
(2)当汽车行驶经过一条网格边时,若其X坐标或Y坐标减小,则应付费用B,否则免付费用。
(3)汽车在行驶过程中遇油库则应加满油并付加油费用A。
(4)在需要时可在网格点处增设油库,并付增设油库费用C(不含加油费A)。
(5)(1)~(4)中的各数N,K,A,B,C均为正整数。
2.2算法设计思想这个题目,应该说是刚开始的时候被他给吓到了,只是想着如何去把所有的条件构造起来,然后使用网络流的方式来解决问题!但是,如果真的是很冷静下来好好地思考这道题目,就会发现如果没有那些限制条件,就是一个求解最长路的题目,这样就可以直接使用SPFA来解决这个问题!关键就是在于这个每次最多只能走K个网格边,这样就是限制了活动的范围,使得有的边无法扩展!因此可以考虑使用这个分层思想的最短路问题!就是通过将每一个点进行拆分,这样,就是相当于一种分类讨论的方式!而分类讨论了之后,就知道哪些边是可以扩展的,哪些边是不能扩展的!关键点就是在于该如何选取变量来分层,这就是因情况而异了!像这道题目之中,就是通过油量的多少来扩展边的!分层思想,说穿了其实就是相当于这个动态规划之中的增加变量的方式来确定状态一样,他们的实质其实都是一样的!2.3设计方法采用的是动态规划的思想来解题,用备忘录的方法进行递归,递归的式子后面写出.不能直接以汽车行驶的费用为目标来进行动态规划,因为最优子结构性质得不到证明.所以必须把油量和费用一起考虑,作为动态规划的对象,此时就有了最优子结构性质.最优子结构性质的证明证明:假设路径M是从起点◎到终点▲的一条最小费用路径,P(x,y)是M经过的一个点(非加油站),且油量和费用为(g,c),现假设有一条新路径Q从起点◎到点P(x,y),使得其在P(x,y)点的油量和费用为(g,c'),其中c'备忘录递归刚开始的时候为每个网格点P(x,y)建立一个记录,初始化时,为该记录存入一个特殊值W,表示汽车未行驶过.那么在汽车行驶过程中,对每个待求的汽车最小费用值COST,先查看其相应的记录项C,如果存储的是初始值W,那么表示这个点P(x,y)是第一次遇到,此时计算出该点的最小费用值,并保存在其相应的记录项中,以备以后查看.若记录项C中存储的不是初始值W,那么表示该问题已经求解过了,其相应的记录项中存储的就是该点的最小费用值COST,此时要取出记录项C的值跟最新的计算出的COST进行比较,取其最小的那个数存入到C中.依此建立记录项C的值,当程序递归完成时,我们也得到了汽车行驶到(n,n)的最小费用值COST.2.4源代码#include "iostream"#include "algorithm"#include "fstream"using namespace std;#define INF 10000/*f[i][j][0]表示汽车从网格点(1,1)行驶至网格点(i,j)所需的最少费用f[i][j][1]表示汽车行驶至网格点(i,j)还能行驶的网格边数s[i][0]表示x轴方向s[i][1]表示y轴方向s[i][2]表示行驶费用f[i][j][0] = min{f[ i+s[k][0] ][ [j+s[k][1] ][0] + s[k][2]} f[i][j][1] = f[ i+s[k][0] ][ [j+s[k][1] ][1] - 1;f[1][1][0] = 0f[1][1][1] = Kf[i][j][0] = f[i][j][0] + A , f[i][j][1] = K 如果(i, j)是油库f[i][j][0] = f[i][j][0] + C + A, f[i][j][1] = K (i, j)不是油库,且f[i][j][1] = 0*/int N; //方形网络规模int A; //汽车在行驶过程中遇到油库应加满油并付加油费Aint C; //在需要时可在网格点处增设油库,并付增设油库费用C(不含加油费A)int B; //当汽车行驶经过一条网格边时,如果其x坐标或y坐标减少,应付费用Bint K; //装满油后,还能行驶K条边int f[50][50][2];int s[4][3] = {{-1,0,0},{0,-1,0},{1,0,B},{0,1,B}};int a[50][50]; //方形网络int dyna(){int i, j, k;for (i=1;i<=N;i++){for (j=1;j<=N;j++){f[i][j][0]=INF;f[i][j][1]=K;}}f[1][1][0] = 0;f[1][1][1] = K;int count = 1;int tx, ty;while(count){count = 0;for(i=1; i<=N; i++){for(int j=1; j<=N; j++){if(i==1 && j==1)continue;int minStep = INF;int minDstep;int step, dstep;for(k=0; k<4; k++) //可走的四个方向{tx = i + s[k][0];ty = j + s[k][1];if(tx<1 || ty<1 || tx>N || ty>N) //如果出界continue;step = f[tx][ty][0] + s[k][2];dstep = f[tx][ty][1] - 1;if(a[i][j] == 1) //如果是油库{step += A;dstep = K;}if(a[i][j]==0 && dstep == 0 && (i!=N||j!=N)) //如果不是油库,且油已经用完{step += A + C;dstep = K;}if(step < minStep) //可以走{minStep = step;minDstep = dstep;}}if(f[i][j][0] > minStep) //如果有更优解 {count++;f[i][j][0] = minStep;f[i][j][1] = minDstep;}}}}return f[N][N][0];}int main(){ifstream fin("car.txt");cout << "输入方格规模:";fin >> N; cout << N;cout << "\n输入装满油后能行驶的网格边数:";fin >> K; cout << K;cout << "\n输入加油费:";fin >> A; cout << A;cout << "\n输入坐标减少时应付的费用:";fin >> B; cout << B; s[2][2] = s[3][2] = B;cout << "\n输入增设油库费用:";fin >> C; cout << C;cout << "\n输入方形网络:\n";for(int i=1; i<=N; i++){for(int j=1; j<=N; j++){fin >> a[i][j];cout << a[i][j] << " ";}cout << endl;}cout << "最优行驶路线所需的费用为:" << dyna() << endl;fin.close();return 0;}2.5最终结果3.总结动态规划(Dynamic Programming, DP)思想启发于分治算法的思想,也是将复杂问题化解若干子问题,先求解小问题,再根据小问题的解得到原问题的解。