重庆大学算法导论跳桩得珠宝问题项目报告(包含报告和源代码)
金块问题_实验报告

一、实验目的1. 理解分金块问题的背景和意义;2. 掌握分治法的基本思想及其在解决分金块问题中的应用;3. 比较不同算法在解决分金块问题时的性能;4. 提高编程能力和算法设计能力。
二、实验内容1. 问题概述分金块问题是一个经典的算法问题。
问题描述如下:老板有n个金块,希望最优秀的雇员得到其中最重要的一块,最差的雇员得到其中最轻的一块。
假设有一台比较重量轻重的天平,要求设计一个算法,在尽可能少的比较次数内,将金块分为三组,使得最优秀的雇员得到最重的金块,最差的雇员得到最轻的金块。
2. 算法分析针对分金块问题,我们可以采用以下两种算法:(1)蛮力法(非递归)蛮力法的基本思想是:遍历所有可能的分组方式,找出最优解。
具体步骤如下:① 将n个金块依次编号为1至n;② 遍历所有可能的分组方式,即从第一个金块开始,将其与其他金块进行分组,然后继续对剩余的金块进行分组,直到分组完毕;③ 对于每一种分组方式,分别找出最重的金块和最轻的金块,并比较其重量;④ 找出所有分组方式中最优的分组方式,即最重的金块和最轻的金块的重量差最小。
(2)分治法分治法的基本思想是将大问题分解为若干个小问题,递归地解决这些小问题,然后合并其结果。
具体步骤如下:① 当n=1时,直接返回该金块;② 将n个金块随机分为两组,分别编号为A和B;③ 分别对A组和B组递归调用分治法,找出每组中的最重金块和最轻金块;④ 比较A组最重金块和A组最轻金块的重量差,以及B组最重金块和B组最轻金块的重量差;⑤ 根据比较结果,确定最终的最重金块和最轻金块。
三、实验步骤1. 实验环境:Python 3.72. 实验数据:随机生成100个金块,重量在1至1000之间。
3. 实验代码(1)蛮力法实现```pythondef brute_force(n):# 初始化金块重量列表weights = [i for i in range(1, n+1)]# 遍历所有可能的分组方式for i in range(1, n//2+1):for j in range(i+1, n-i+1):for k in range(j+1, n-j+1):# 计算分组方式下的最重金块和最轻金块的重量差diff_a = max(weights[i-1:k]) - min(weights[i-1:k])diff_b = max(weights[k:n]) - min(weights[k:n])# 更新最优解if diff_a < diff_b:best_a = max(weights[i-1:k])best_b = min(weights[i-1:k]) else:best_a = max(weights[k:n]) best_b = min(weights[k:n]) return best_a, best_b# 测试n = 100print(brute_force(n))```(2)分治法实现```pythondef divide_and_conquer(weights, left, right):# 当只剩一个金块时,返回该金块if left == right:return weights[left]# 将金块分为两组mid = (left + right) // 2max_a = max(weights[left:mid])min_a = min(weights[left:mid])max_b = max(weights[mid:right+1])min_b = min(weights[mid:right+1])# 比较两组金块的重量差if max_a - min_a < max_b - min_b:return max_a, min_aelse:return max_b, min_b# 测试n = 100weights = [i for i in range(1, n+1)]print(divide_and_conquer(weights, 0, n-1))```四、实验结果与分析1. 实验结果(1)蛮力法:当n=100时,运行时间约为0.6秒;(2)分治法:当n=100时,运行时间约为0.001秒。
(重庆理工大学计算机学院)编译原理课程设计报告

编译原理课程设计报告实验名称编译原理课程设计班级学号姓名指导教师实验成绩2013 年06月一、实验目的➢通过设计、编写和调试,将正规式转换为不确定的有穷自动机,再将不确定的有穷自动机转换为与之等价的确定的有穷自动机,最后再将确定有穷自动机进行简化。
➢通过设计、编写和调试构造LR(0)项目集规范簇和LR分析表、对给定的符号串进行LR分析的程序,了解构造LR(0)分析表的步骤,对文法的要求,能够从文法G出发生成LR(0)分析表,并对给定的符号串进行分析。
二、实验内容➢正规式——>NFA——>DFA——>MFA1.正规式转化为不确定的有穷自动机(1)目的与要求通过设计、编写和调试将正规式转换为不确定的有穷自动机的程序,使学生了解Thompson算法,掌握转换过程中的相关概念和方法,NFA的表现形式可以是表格或图形。
(2)问题描述任意给定一个正规式r(包括连接、或、闭包运算),根据Thompson算法设计一个程序,生成与该正规式等价的NFA N。
(3)算法描述对于Σ上的每个正规式R,可以构造一个Σ上的NFA M,使得L(M)=L(R)。
步骤1:首先构造基本符号的有穷自动机。
步骤2:其次构造连接、或和闭包运算的有穷自动机。
(4)基本要求算法实现的基本要求是:(1) 输入一个正规式r;(2) 输出与正规式r等价的NFA。
(5)测试数据输入正规式:(a|b)*(aa|bb)(a|b)*得到与之等价的NFA N(6)输出结果2.不确定的有穷自动机的确定化(1)目的与要求通过设计、编写和调试将不确定的有穷自动机转换为与之等价的确定的有穷自动机的程序,使学生了解子集法,掌握转换过程中的相关概念和方法。
DFA的表现形式可以是表格或图形。
(2)问题描述任意给定一个不确定的有穷自动机N,根据算法设计一个程序,将该NFA N变换为与之等价的DFA D。
(3)算法描述用子集法将NFA转换成接受同样语言的DFA。
《算法设计与分析》课程实验报告 (回溯法(二))

《算法设计与分析》课程实验报告实验序号:10实验项目名称:实验十一回溯法(二)一、实验题目1.图的着色问题问题描述:给定无向连通图G和m种不同的颜色。
用这些颜色为图G的各顶点着色,每个顶点着一种颜色。
如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。
图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
2.旅行商问题问题描述:给出一个n个顶点的带权无向图,请寻找一条从顶点1出发,遍历其余顶点一次且仅一次、最后回到顶点1的最小成本的回路——即最短Hamilton回路。
3.拔河比赛问题描述:某公司的野餐会上将举行一次拔河比赛。
他们想把参与者们尽可能分为实力相当的两支队伍。
每个人都必须在其中一只队伍里,两队的人数差距不能超过一人,且两队的队员总体重应该尽量接近。
4.批处理作业调度问题描述:给定n个作业的集合J=(J1,J2, .. Jn)。
每个作业J都有两项任务分别在两台机器上完成。
每个作业必须先由机器1处理,再由机器2处理。
作业i需要机器j的处理时间为tji(i=1,2, ..n; j=1,2)。
对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间,则所有作业在机器2上完成处理的时间和,称为该作业调度的完成时间和。
批处理作业调度问题要求,对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。
二、实验目的(1)通过练习,理解回溯法求解问题的解状态空间树与程序表达的对应关系,熟练掌握排列树、子集树的代码实现。
(2)通过练习,体会减少搜索解空间中节点的方法,体会解的状态空间树的组织及上界函数的选取对搜索的影响。
(3)通过练习,深入理解具体问题中提高回溯算法效率的方法。
(4)(选做题):在掌握回溯法的基本框架后,重点体会具体问题中解的状态空间搜索时的剪枝问题。
三、实验要求(1)每题都必须实现算法、设计测试数据、记录实验结果,并给出时间复杂度分析。
四、实验过程(算法设计思想、源码)1.图的着色问题(1)算法设计思想用邻接矩阵a[i][j]存储无向图,对于每一个顶点有m种颜色可以涂。
算法导论 7.1 例题

算法导论 7.1 例题
《算法导论》第7.1节主要讨论了动态规划算法,这是一种常
用的解决优化问题的方法。
在这一节中,书中提到了一些例题来帮
助读者更好地理解动态规划的原理和应用。
其中一个例题是“钢条
切割问题”,这是动态规划算法中经典的问题之一。
钢条切割问题是这样的,给定一段长度为n英寸的钢条和一个
价格表,包含不同尺寸钢条的价格。
要求找到切割钢条的方案,使
得销售收益最大化。
动态规划的思想是将原问题分解为若干个子问题,通过求解子
问题的最优解来得到原问题的最优解。
对于钢条切割问题,可以将
钢条切割的方式分为不同的子问题,然后逐步求解这些子问题得到
最优解。
具体的解题思路是,假设长度为n的钢条的最优切割方案为
m(n)。
我们可以将钢条切割为长度为i和长度为n-i的两部分,然
后分别求解这两部分的最优切割方案,最后将它们的收益相加即可
得到m(n)。
通过对不同的i进行遍历,我们可以找到m(n)的最大值,从而得到原问题的最优解。
通过这个例题,读者可以深入理解动态规划算法的核心思想和具体应用。
除了钢条切割问题,书中还介绍了其他一些动态规划的经典问题,通过学习这些例题,读者可以更好地掌握动态规划算法的原理和技巧,为解决实际问题提供有力的工具和思路。
算法设计与分析实验报告

实验一找最大和最小元素与归并分类算法实现(用分治法)一、实验目的1.掌握能用分治法求解的问题应满足的条件;2.加深对分治法算法设计方法的理解与应用;3.锻炼学生对程序跟踪调试能力;4.通过本次实验的练习培养学生应用所学知识解决实际问题的能力。
二、实验内容1、找最大和最小元素输入n 个数,找出最大和最小数的问题。
2、归并分类将一个含有n个元素的集合,按非降的次序分类(排序)。
三、实验要求(1)用分治法求解问题(2)上机实现所设计的算法;四、实验过程设计(算法设计过程)1、找最大和最小元素采用分治法,将数组不断划分,进行递归。
递归结束的条件为划分到最后若为一个元素则max和min都是这个元素,若为两个取大值赋给max,小值给min。
否则就继续进行划分,找到两个子问题的最大和最小值后,比较这两个最大值和最小值找到解。
2、归并分类使用分治的策略来将一个待排序的数组分成两个子数组,然后递归地对子数组进行排序,最后将排序好的子数组合并成一个有序的数组。
在合并过程中,比较两个子数组的首个元素,将较小的元素放入辅助数组,并指针向后移动,直到将所有元素都合并到辅助数组中。
五、源代码1、找最大和最小元素#include<iostream>using namespace std;void MAXMIN(int num[], int left, int right, int& fmax, int& fmin); int main() {int n;int left=0, right;int fmax, fmin;int num[100];cout<<"请输入数字个数:";cin >> n;right = n-1;cout << "输入数字:";for (int i = 0; i < n; i++) {cin >> num[i];}MAXMIN(num, left, right, fmax, fmin);cout << "最大值为:";cout << fmax << endl;cout << "最小值为:";cout << fmin << endl;return 0;}void MAXMIN(int num[], int left, int right, int& fmax, int& fmin) { int mid;int lmax, lmin;int rmax, rmin;if (left == right) {fmax = num[left];fmin = num[left];}else if (right - left == 1) {if (num[right] > num[left]) {fmax = num[right];fmin = num[left];}else {fmax = num[left];fmin = num[right];}}else {mid = left + (right - left) / 2;MAXMIN(num, left, mid, lmax, lmin);MAXMIN(num, mid+1, right, rmax, rmin);fmax = max(lmax, rmax);fmin = min(lmin, rmin);}}2、归并分类#include<iostream>using namespace std;int num[100];int n;void merge(int left, int mid, int right) { int a[100];int i, j,k,m;i = left;j = mid+1;k = left;while (i <= mid && j <= right) {if (num[i] < num[j]) {a[k] = num[i++];}else {a[k] = num[j++];}k++;}if (i <= mid) {for (m = i; m <= mid; m++) {a[k++] = num[i++];}}else {for (m = j; m <= right; m++) {a[k++] = num[j++];}}for (i = left; i <= right; i++) { num[i] = a[i];}}void mergesort(int left, int right) { int mid;if (left < right) {mid = left + (right - left) / 2;mergesort(left, mid);mergesort(mid + 1, right);merge(left, mid, right);}}int main() {int left=0,right;int i;cout << "请输入数字个数:";cin >> n;right = n - 1;cout << "输入数字:";for (i = 0; i < n; i++) {cin >> num[i];}mergesort(left,right);for (i = 0; i < n; i++) {cout<< num[i];}return 0;}六、运行结果和算法复杂度分析1、找最大和最小元素图1-1 找最大和最小元素结果算法复杂度为O(logn)2、归并分类图1-2 归并分类结果算法复杂度为O(nlogn)实验二背包问题和最小生成树算法实现(用贪心法)一、实验目的1.掌握能用贪心法求解的问题应满足的条件;2.加深对贪心法算法设计方法的理解与应用;3.锻炼学生对程序跟踪调试能力;4.通过本次实验的练习培养学生应用所学知识解决实际问题的能力。
重庆大学数字逻辑实验报告

4、实验结果及分析和(或)源程序调试过程
仿真结果:
RTL分析:
效果图:
J15为输入a,L16为输入b,M13为输入s,H17为输出c
当s为0,输出为a的输入,如下图
当s为1,输出为b的输入,如下图
6)综合、实现、生成bit流,下载到Nexys4开发板进行验证;三、实Biblioteka 过程或算法真值表:s
a
b
c
0
0
0
0
0
0
1
0
0
1
0
1
0
1
1
1
1
0
0
0
1
0
1
1
1
1
0
0
1
1
1
1
Block Design:
Verilog代码:
module shiyan2(
input a,
input b,
input s,
output c
一实验目的多路选择器ip核的封装与调用二实验项目内容1将实验一中的与门演示过程或门非门与非门等基本门电路封装成ip2调用封装的ip核用blockdesign设计一个一位的2多路选择器可演示过程
《脉冲电路与数字逻辑》实验报告
姓名
王博韬
年级
2015级
学号
20154320
专业、班级
计科6
实验名称
多路选择器--IP核的封装与调用
2)调用封装的IP核,用Block Design设计一个一位的2选1多路选择器(可演示过程);
3)用verilogHDL语言编写一个一位的2选1多路选择器(可提供代码);
4)分别用RTL分析2)、3)中的电路设计(学会看RTL电路图);
算法导论答案 (4)

算法导论答案第一章:算法概述啊算法的定义算法是一系列解决问题的明确指令。
它是一个有穷步骤集,其中每个步骤或操作由确定性和可行性特征。
算法是通过将预期的输入转换为输出来解决问题的工具。
第二章:插入排序插入排序的思想插入排序是一种简单直观的排序算法,其基本思想是将待排序的序列分为已排序和未排序两部分,每次从未排序的部分中取出一个元素,并将其插入到已排序部分的正确位置,直到所有元素都被排序。
插入排序的算法实现以下是插入排序的伪代码:INSERTION-SORT(A)for j = 2 to A.lengthkey = A[j]// Insert A[j] into the sorted sequence A[1.. j-1].i = j - 1while i > 0 and A[i] > keyA[i + 1] = A[i]i = i - 1A[i + 1] = key插入排序的时间复杂度插入排序的时间复杂度为O(n^2),其中n是排序的元素个数。
虽然插入排序的最坏情况下的复杂度很高,但是对于小规模的数据集,插入排序是一种较快的排序算法。
第三章:分治策略分治策略的基本思想分治策略是一种解决问题的思想,它将问题的规模不断缩小,直到问题足够小而可以直接解决。
然后将子问题的解合并起来,得到原问题的解。
分治策略的应用实例一种经典的应用分治策略的算法是归并排序。
归并排序将待排序的序列划分为两个子序列,分别排序后再将两个有序子序列合并为一个有序序列。
以下是归并排序的伪代码:MERGE-SORT(A, p, r)if p < rq = floor((p + r) / 2)MERGE-SORT(A, p, q)MERGE-SORT(A, q + 1, r)MERGE(A, p, q, r)MERGE(A, p, q, r)n1 = q - p + 1n2 = r - qlet L[1..n1+1] and R[1..n2+1] be new arraysfor i = 1 to n1L[i] = A[p + i - 1]for j = 1 to n2R[j] = A[q + j]L[n1 + 1] = infinityR[n2 + 1] = infinityi = 1j = 1for k = p to rif L[i] <= R[j]A[k] = L[i]i = i + 1elseA[k] = R[j]j = j + 1分治策略的时间复杂度归并排序的时间复杂度为O(nlogn),其中n是待排序序列的长度。
算法分析与复杂性理论-实验报告-求最近点对的问题

深圳大学实验报告教务部制1.对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。
2.要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。
3.要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。
4.分别对N=100,1000,10000,100000 ,统计算法运行时间,比较理论效率与实测效率的差异,同时对蛮力法和分治法的算法效率进行分析和比较。
5.利用Unity3D输出分治算法中间每个步骤的计算结果,并增设help按钮,详细解释算法思想。
算法思想提示1.预处理:根据输入点集S中的x轴和y轴坐标进行排序,得到X和Y,很显然此时X和Y 中的点就是S中的点。
2.点数较少时的情形直接计菊只有三个疽3.点数|S|>3时,将平面点集S分割成为大小大致相等的两个子集S L和S R,选取一个垂直线L作为分割直线,考虑X L和X R,Y L和Y R,这里还需要排序吗?4.两个递归调用,分别求出S L和S R中的最短距离为d i和d r。
5.取d=min(dl, dr),在直线L两边分别扩展d,得到边界区域Y, Y'是区域Y中的点按照y坐标值排序后得到的点集,Y'又可分为左右两个集合Y 'L和Y 'RL.一L<dL+d6.对于Y'L中的每一点,检查Y'R中的点与它的距离,更新所获得的最近距离实验过程及内容:(实验代码已作为附件提交,名为“算法实验二.cpp)当点的数量小丁3时,直接计算,当点的个数大丁3时,采用分治法当N=1时当N=2时只有两个点,最近点对就是这两个点测试数据为(1,1 ) (2,2)预期结果为d=1.414使用蛮力法求最近点对,核心代码如下〃求距离平方的函数double Distinyuish2(Node a t Node b)return ((d.x-b.x)*(a.x-b.x)) + ((a.y-tj.y)*(a.y-b.y));〃蛮力法求最近对uoid BriiteForce(const HList & L,CloseHode & cnode,int begin v int end)For(int i=t)egin;i<=end;i*+)Forfinit j<-end;j + + )double space = Di stinguish2(L.data[i],L.data[j]); iF<sp^ce<cnode.5pact)cnode_a=L.data[l]; cnade.b=L.data[j]; cnode .space=space;(计算两点之间的距离,分别将每个点与其它点的距离求出来,找出最近点距离)当N>3时,使用分治法的情况核心代码如下:;15E 〃当n》3时进行分治<APOIHT *SL-nev fi_POINT[(high-low)/2+1];■[POINT *SR-nev A>0IHT[ (hi^i-low)/2];n)= (high-low)/2; /成曦(组以缺)界划分为茜半j=k=t);for(i=B;i<=high-lou;i*+)if(V[i]*indeK<=n){SL[ ji ] T [i];〃收集左边子集中的最近点对pise{SR[kt+]=Y[i];〃收集右边子集中的最近点对>)closest (K.SL,low,■,al,bl,dl);//i+ 算左边子集的最近点对closes t (X,Sft,m+1,tiigh,ar.br,dr 算右边子靠的最近点对if(dl<dr);b=bl;d=dl;}else(a=ar;b=tjr ;d=dr;POIlfT *2=new POI NT[higti-low+1 ];k=o;For(i=B;i<=t*igh-lcw;i*+)//收集距离中线?寤小于U的元素,保存S懒组?中(iF(f=abstX[n] .x-V[l] .x)<d>2(k].x=V[i],x;£[k^+].y=V[i]^:for(i-l;l<k;l++)< far(j=i>1;(-y-Z[i] j++)dl=aist(Z[i]^[j]);{a = 2[iJ;b - Z[j];ri = d) ■当N=6时,给定一组测试数据下面随机生成N个点的平面坐标,求解最近点对。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
大学项目报告项目题目:跳桩得珠宝问题学院:专业班级:计科年级:2011级姓名:学号:完成时间:2013 年 6 月7 日指导教师:波大学教务处制项目报告正文一.问题描述有m排n列的柱桩,每一排的柱桩从左向右标号为1,2,…,n,且在每个柱桩上预先放好价值不一样的宝石。
现在有位杂技演员从第一排的第1号柱桩开始跳跃,每次都必须跳到下一排的柱桩上,且每次跳跃最多只能向左或向右移动一个桩子。
也就是说如果现在杂技演员站在第j号桩上,那么他可跳到下一排的第j号桩上,也可跳到下一排的第j-1 (if j>1)或者j+1 (if j<n) 号桩上,并得到桩上的宝石。
计算出一条最佳的跳跃顺序,使杂技演员获得的宝石的总价值最大。
二.算法思想问题抽象:对于这个问题,可以抽象为:从顶部出发,在每一结点可以选择向左走,向下走或是向右走,一直走到底层,要求找出一条路径,使路径上的值最大。
问题分析:这道题如果用枚举法,在数塔层数稍大的情况下(如40),则需要列举出的路径条数将是一个非常庞大的数目。
如果用贪心法又往往得不到最优解。
在用动态规划考虑数塔问题时可以自顶向下的分析,自底向上的计算。
于是在确定使用动态规划的情况下,对该问题进行分析。
算法思想:从顶点出发时到底向左走,向下走还是向右走应取决于是从哪个方向走能取到最大值,只要左中右三道路径上的最大值求出来了才能作出决策。
同样的道理下一层的走向又要取决于再下一层上的最大值是否已经求出才能决策。
这样一层一层推下去,直到倒数第二层时就非常明了。
所以实际求解时,可从底层开始,层层递进,最后得到最大值。
首先,我可以确定,对于矩阵可以用一个二维数组dp储存它,并且可以用(i,j)描述一个数字在矩阵中的位置。
对于中间的一个点来说,想经过它则必须经过它的上方或左上或右上,也就是说经过这个点的数字和最大等于经过上方或左上方或右上方的所得的“最大和”中一个更大的加上这个点中的数字。
显然这个定义满足最优子结构。
三.递推方程式设计一个二维状态opt[i,j]表示走到第i行第j列时经过的数字的最大和。
决策是opt[i-1,j] 或opt[i-1,j-1]或opt[i-1,j+1]中一个更大的加上(i,j)点的数字。
对于一个点只考虑上面或左上或右上即前一阶段,满足无后效性。
状态转移方程(顺推):opt[i-1,j]+dp[i,j] (j=1)opt[i,j]= opt[i-1,j-1]+ dp[i,j] (j=max)max{opt[i-1,j],opt[i-1,j-1]}+ dp[i,j] (1<j<max)实现时可以将opt[i,j]的左右边界定义的大点,初始opt[i,j]=0,由于在j=1时opt[i-1,j-1]=0,opt[i-1,j]>=0所以方程也可以这样写:opt[i,j]=max{opt[i-1,j],max(opt[i-1,j-1],opt[i-1,j+1])}+a[i,j]同理j=i时方程也可以写成上面那样,所以方程综合为:opt[i,j]=max{opt[i-1,j],max(opt[i-1,j-1],opt[i-1,j+1])}+a[i,j] (1<j<max)显然答案是走到底后的一个最大值,即:ans=max{opt[n,i]} (1<=i<=n)其实从上往下走和从下往上走结果是一样的,但是如果从下往上走结果就是opt[1,1]省下求最大值了,所以方程进一步改动(逆推):opt[i,j]=max{opt[i+1,j],max(opt[i-1,j-1],opt[i-1,j+1])}+a[i,j](0<j<=i)四.最优子结构性质对于中间的一个点来说,想经过它则必须经过它的上方或左上或右上,也就是说经过这个点的数字和最大等于经过上方或左上方或右上方的所得的“最大和”中一个更大的加上这个点中的数字。
显然这个定义满足最优子结构。
以此为递推关系。
五.程序结构的描述此程序主要分为以下四个部分文件读入(从文件中读取矩阵的值应存入二维数组中)最大值计算(用递推式推出)明确路径(用一个path数组记录下动态)在文件中显示(读入文件)最大值的计算主要用上述递推式,路径的求得是定义了一个二维数组path,用这个二维数组存取dp中相对应位置的路线动态,比如说在(i,j)点在接下来一行要向右,我们就将path[i][j]赋值为1,则循环时用i++;j+=path[i][j],就将位置右移一个,同理可令向左为-1,向下为0.for(int i = 0, j = 0; i<M; ++i){file2<< "[" << i+1<< "," << j+1 << "]" << " -> ";j += path[i][j];}六.计算复杂度分析此实验中,作为基本操作的原操作是max();即比较函数,在循环中,进行了N^2次,而比较函数其运行时间为常数O(1),故计算最大值部分T(n)=O(n^2);同理,在路径输出部分,关键代码是j+=path[i][j];其T(n)=O(n);该算法总的时间复杂度T(n)=O(n^2)。
七.测试结果: test.txt文件:柱桩20排20列:柱桩4排4列:全部代码:#include <iostream>#include <algorithm>#include <fstream>using namespace std;int const MAX =20;int M,N,num=0;int main(){int count=0;fstream file1,file2;file1.open("test.txt",ios::in);if(!file1)cout<<"input file not founded"<<endl;cout<<" **************跳桩得珠宝****************"<<endl;cout<<" *************1柱桩20排20列**************"<<endl;cout<<" *************2自定义柱桩排列************"<<endl;cout<<"请输入您的选择:";cin>>num;if(num==2){cout<<"请输入排与列(排与列均小于20):"<<endl;cin>>M>>N;}else{if(num==1)M=N=MAX;elsecout<<"输入不符,重新启动!";}int dp[MAX][MAX] = {0};int path[MAX][MAX] = {MAX};//描写路径的坐标 while(!file1.eof())//是否到文件结尾{for(int i=0;i<M;i++)for(int j=0;j<N;j++){file1>>dp[i][j];count++;}if(count==M*N)break;}file2.open("output.txt",ios::out);if(!file2)cout<<"output file not founded"<<endl;for(int i=0;i<M;i++){for(int j=0;j<N;j++){file2<<dp[i][j];file2<<",";}file2<<"\n";}file1.close();for(int i=M - 2; i>=0; i--){for(int j=0; j<=N-1; j++){if(j==0){dp[i][j] = max(dp[i + 1][j],dp[i+1][j+1]) + dp[i][j];if (dp[i+1][j] > dp[i+1][j+1]) //正下方大path[i][j] = 0; //选择正下方else //右边大path[i][j] =1; //选择右边}else{dp[i][j] = max(dp[i + 1][j-1], max(dp[i + 1][j],dp[i+1][j+1])) + dp[i][j];if((dp[i+1][j-1] >=dp[i+1][j])&&(dp[i+1][j-1] >=dp[i+1][j+1])) path[i][j] = -1;elseif((dp[i+1][j] > dp[i+1][j-1])&&(dp[i+1][j] >=dp[i+1][j+1])) //正下方大path[i][j] = 0; //选择正下方else //右边大path[i][j] = 1; //选择右边}}}file2<<dp[0][0]<<" (最大价值)"<< endl;for(int i = 0, j = 0; i<M; ++i){file2<<j+1 <<endl;j += path[i][j];}return EXIT_SUCCESS;}参考资料:Algorithm Design, Jon Kleiberg. Eva Tardos, Cornell University。