算法设计与分析 钻石金字塔问题

一、 问题描述

现在你的任务是从金字塔的顶端向金字塔的底端收集钻石,并且尽可能收集价值高的钻石,但是只能从一块砖斜向左下或斜向右下走到另一块砖上,如从上图从用红色 A 标记的砖走向用蓝色 B 标记的砖上。富翁希望 heimengnan 找到一个收集最高价值钻石的路线,并且把可能收集的最大价值告诉富翁。

二、 算法描述及思考过程

拿到矿工问题,我第一个想法就是贪心算法,从上往下,每次都取大的。但是遇到以下状况时,贪心算法取不到最优解。最优解应该为 5+1+100=106,但是贪心算法求的是 5+10+2=17。

第二个想法是先遍历一遍,找到该金字塔中价值最大的位置,再根据它往上往下找,但是这样复杂度太高,而且也不能保证取得最优解。

所以想到了用分治法。

如图,比如现在要填价值为“3”这个位置的和,则判断下它的左边和右边哪个价值和更大,则 选 择 哪 边 , 那 么 3 这 个 位 置 的 和 则 为 3+ 更 大 的 一 方 。 即 SUM[i]max=A[i]+max{SUM[left],SUM[right]};//SUM 为存储此位置能拿到的最大价值,A 为原金字塔数组。

2.1 代码如下:

int firstSolution(int A[],int top,int nf,int n,int sf,int sum[])
/*A[]-金字塔原数组,top-当前处于塔顶元素的序号,nf-当前 top 元素所处层数,n-金字塔元素总数,sf-金字塔总层数,sum-当前求得和*/
{   int left,right;if(top>=n-sf+1&&top<=n)//top 元素位于最后一行       return(sum[top]=A[top]);   else{left=firstSolution(A,top+nf,nf+1,n,sf,sum);right=firstSolution(A,top+nf+1,nf+1,n,sf,sum);
//和等于 top 处元素和左右之间大的那个相加if(left>right){return(sum[top]=left+A[top]);}          else{return(sum[top]=right+A[top]);}}
}

因为还要寻找路径,所以根据 sum 数组的值,查找路径。

2.2 代码如下:

void findway(int sum[],int A[],int sf)
{int *way;way=new int[sf+1];int k=1;for(int i=1; i<=sf; i++) //i 为当前层数{if(sum[k+i]>=sum[k+i+1])//左边大{way[i]=A[k+i];k+=i;}else{way[i]=A[k+i+1];k+=i+1;}}way[0]=A[1];//第一个必须经过   cout<<"路径"<<endl;for(int j=0; j<sf; j++){cout<<way[j]<<" ";}cout<<endl;
}

运行结果如下:

结果是正确的。

通过之前几次测试也可知,递归算法在相同时间复杂度时所耗费的时间远大于非递归算法,所以要想办法消除递归。

分治法的递归是从头向下走,递归深入金字塔,再把值返回来比较,所以要消除递归,我们可以从底下往上算。此时的复杂度为 O(n)。

2.3 代码如下:

int secondSolution(int A[],int n,int sf,int sum[]) //消除递归,从底往上走
//*A[]-金字塔原数组,n-金字塔总元素总数,sf-金字塔总层数,sum-当前求得和*/
{   int i;int nf;//当前层数for(i=(sf*(sf-1)/2)+1; i<=n; i++) //最后一行{sum[i]=A[i];}nf=sf-1;for(i=sf*(sf-1)/2; i>=1; i--) {if(sum[i+nf]>=sum[i+nf+1]){sum[i]=A[i]+sum[i+nf];}else{sum[i]=A[i]+sum[i+nf+1];}if(i==(nf*(nf-1)/2)+1){nf--;//到了每行开头,则行数-1,因为下一个元素就是上一行的了}}return sum[1];
}

运行结果如下:

运行结果正确。

此算法和张舒阳同学在课上讲的 betterpyramid 算法基本一致,所以借鉴她之后的优化,可以降低空间复杂度,即直接把算出来的 sum 存到 A 数组中,因为不会再回头,所以 A 中用过的元素不会再用第二遍,所以可以直接替换掉。大大降低了空间复杂度,也省去了填充最后一行的 sum 数组,时间复杂度变为 O(n-sf)

2.4 代码如下:

int thirdSolution(int A[],int n,int sf)//直接存 A 数组中,不用 sum 数组
{int i,nf;nf=sf-1;if(sf==1)//只有一层{   return A[1];}    else{for(i=n-sf; i>=1; i--){if(A[i+nf]>=A[i+nf+1]){=A[i]+A[i+nf];}              else{=A[i]+A[i+nf+1];}if(i==(nf*(nf-1)/2)+1){nf--;//到了每行开头,则行数-1,因为下一个元素就是上一行的了}}}return A[1];
}

运行结果如下:

运行结果正确。

三、 时间复杂度测试:

根据数据得出以下折线图:

经几次测试发现,在层数逐渐增大时,分治法所用时间明显增加,斜率也十分大。可见其时间复杂度之高。

于是抛弃分治法,用了更高的重复次数和更多的层数测试后两个算法之间的差距。

测试了几组,发现因为差距不大,用 s 作为单位观察不出差距,所以把单位换成 ms。

得到数据如下:

根据数据得到如下折线图:

发现两个算法增长的斜率几乎一致,但是仍在层数增大时花费时间差增大,因为差的是 O(sf),和层数有关。

四、 测试截图:

包括分治法,重复次数为 1000 次








基于C++的钻石金字塔问题算法设计相关推荐

  1. 基于SIMD的AVS整数反变换算法设计与优化

    基于SIMD 的AVS 整数反变换算法设计与 优化 王玲娟,张刚** 作者简介:王玲娟,(1987-),女,在读硕士,主要研究方向:视频解码算法 通信联系人:张刚,(1953-),男,教授,主要研究方 ...

  2. 基于Python+Open CV的手势识别算法设计

    素材资料下载: 基于Python+OpenCV的手势识别算法设计源代码材料-机器学习文档类资源-CSDN下载采用Python的集成开发环境Pycharm进行本次课程设计,在Pycharm中进行需要库( ...

  3. 孙玄辜教授:基于Linux内核的时间轮算法设计实现【附代码】

    文章目录 1.时间轮算法基本思想 2.定时器的添加 3.定时器到期处理 孙玄:毕业于浙江大学,现任转转公司首席架构师,技术委员会主席,大中后台技术负责人(交易平台.基础服务.智能客服.基础架构.智能运 ...

  4. 基于MATLAB有噪声语音信号处理算法设计

    获取项目源文件,联系Q:1415736481,可指导毕设,课设 摘要 滤波器设计在数字信号处理中占有极其重要的地位,FIR数字滤波器和IIR滤波器是滤波器设计的重要组成部分.利用MATLAB信号处理工 ...

  5. 基于DSP的注塑机运动控制器和算法设计

    将 D S P 作 为 下 位 机 , ARM 作 为 上 位 机 设 计 了 精 密 的 注 塑 机 控 制 系 统 , 下 位 机 用 于 控 制 算 法 的 运 行 以 及 I/ O 控 制 , ...

  6. “华为杯”研究生数学建模竞赛2020年-【华为杯】A题:基于通信仿真的载波恢复算法设计与 ASIC 实现(附获奖论文及matlab代码实现)

    目录 摘 要: 1. 问题重述 1.1 问题背景 1.2 问题要求 2. 模型假设 3. 符号说明

  7. 【毕业设计】基于程序化生成和音频检测的生态仿真与3D内容生成系统----程序化生成地形算法设计

    2 程序化生成地形算法设计 Input: Output: 2.1 地形的生成 程序化生成地形算法是一种在计算机中生成地形的方法,通常用于游戏开发和虚拟现实应用.下面是几种常见的程序化生成地形算法: D ...

  8. 基于matlab的捷联惯导算法设计及仿真,基于 Matlab 的捷联惯导算法设计及仿真1doc.doc...

    基于 Matlab 的捷联惯导算法设计及仿真1doc 基于 Matlab 的捷联惯导算法设计及仿真1 严恭敏 西北工业大学航海学院,西安 (710072) E-mail:yangongmin@163. ...

  9. c++多边形扫描线填充算法_基于3DGIS技术的梯形格网构建及其简化算法设计

    传统矢量地图LOD绘制流程包含简化.剖分与渲染三个步骤.由上述分析可知,传统矢量地图LOD绘制流程中简化与剖分是两个独立的过程,重复的剖分计算导致其渲染效率相对低下.梯形格网方法解决了传统方法中重复剖 ...

  10. 一种基于加密域的数字图像水印算法的设计与实现(附Matlab源码)

    一种基于加密域的数字图像水印算法的设计与实现 项目介绍 毕设项目 题目:一种基于加密域的数字图像水印算法的设计与实现 随着数字媒体技术的发展,数字媒体版权的保护得到了越来越多人的重视,数字水印技术作为 ...

最新文章

  1. 清华大佬教你一招最便捷搭建 Zookeeper 的方法!
  2. python 信号量,Event, 定时器
  3. 微服务实战:从架构到发布(二)
  4. 【神经网络与深度学习】【C/C++】比较OpenBLAS,Intel MKL和Eigen的矩阵相乘性能
  5. Android 插件框架机制之Small
  6. 安卓实训项目:音乐播放器3.0——实训报告3
  7. Python3.4 django使用mysql
  8. Halcon :畸变矫正与标定(2)
  9. ajax 五种状态,ajax的五种状态
  10. 产品经理欲哭无泪的瞬间(太真实了)
  11. 2020年最好用的手机是哪一款_2020年10款最好用的健康秤
  12. 【Java】@transient代表着什么
  13. 用计算机坑人,10大坑人专业,坑你没商量!
  14. Spring在多线程中bean的注入问题
  15. 第四季-专题3-嵌入式Linux内核制作
  16. 关于SI4463和AIS的学习笔记
  17. SpringCloud版本Hoxton SR5 --- 第五讲:zuul 路由、过滤、容错与回退、集群、高可用
  18. 计算机英语 自我介绍,计算机专业英文自我介绍
  19. python爬虫爬取网易云音乐下载_Python爬虫实践-网易云音乐!没有版权又如何!照样爬取!...
  20. 深入理解Netty编解码、粘包拆包、心跳机制

热门文章

  1. Reminders在电商推荐中的价值
  2. 618好物推荐:基于HarmonyOS和小熊派BearPi-HM Nano的护花使者
  3. vbox vdi磁盘注册_克隆Virtualbox的vdi硬盘 和 修改uuid
  4. 如何用Java写出热门大鱼吃小鱼游戏
  5. 字符画-Python
  6. 2022 年牛客多校第五场补题记录
  7. python语句用什么隔开_在python中使用字典时用什么隔开
  8. WebGL three.js 3D 场景
  9. Sisyphus----a log data-mining toolkit安装过程
  10. android mjpg格式,Camera常用格式MJPEG和jpeg-turbo库