秒懂算法 | 汉诺塔问题与木棒三角形

图片

在数学与计算机科学中,递归(recursion)是指一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。递归的能力在于用有限的语句定义对象的无限集合。一个递归问题可分为递推和回归两个阶段。在递推阶段,把较复杂问题(规模为n)的求解推到比原问题简单一些的问题(规模小于n)的求解;在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解。

只有同时满足下面三个条件的问题,才能用递归解决。

(1) 一个问题可以转化为一个与原问题相似的、规模较小的子问题来求解。比如,在n的阶乘的计算中,将n的阶乘的问题转化为n-1的阶乘乘以n,此问题便可解决。

(2) 这个问题与分解之后的子问题,除数据规模不同,求解思路完全一样。比如,n的阶乘问题中,求解n的阶乘的思路,和求解n-1的阶乘的思路是一模一样的。

(3) 存在递归终止条件。

把问题分解为子问题,再把子问题分解为子子问题,一层一层分解下去,不能存在无限循环,这就需要有终止条件。比如,n的阶乘问题中,0或1的阶乘为1,也就是f(1)=1,f(0)=1,这就是递归的终止条件。

递归是很多算法实现的基础,是程序设计中的一种重要思想和机制,如分治、深度优先搜索、动态规划等算法中均用到递归思想。

01、汉诺塔问题

汉诺(Hanoi)塔问题是一个经典的运用递归方法解决问题的例子。

问题描述:

汉诺塔是一个发源于印度的益智游戏,也叫河内塔。相传它源于印度神话中的大梵天创造的三根金刚柱,一根柱子上叠着上下从小到大64个黄金圆盘。大梵天命令婆罗门将这些圆盘按从小到大的顺序移动到另一根柱子上,其中大圆盘不能放在小圆盘上面。当这64个圆盘移动完的时候,世界就将毁灭。

那么,好多人会问64个圆盘移动到底会花多少时间?古代印度距离现在已经很远,这64个圆盘还没移动完么?我们通过计算看完成这个任务到底要多少时间?计算结果非常恐怖,移动圆盘的次数为2n-1,即18446744073709551615,假设移动一次圆盘用时一秒,一年为31536000秒。那么,18446744073709551615/31536000约等于584942417355年,即约为5850亿年。目前太阳寿命约为50亿年,太阳的完整寿命大约100亿年。所以,整个人类文明都等不到移动完整圆盘的那一天。很多人对汉诺塔的解法产生了兴趣。从一阶汉诺塔到N阶汉诺塔它们是否有规律性的算法?能否编程输出每一次移动的方法呢?这就是本例要解决的问题。

输入:

输入一个正整数n,表示有n个圆盘在第一根柱子上。

输出:

输出操作序列,格式为move t from x to y。每个操作一行,表示把x柱子上的编号为t的盘片挪到柱子y上。柱子编号为a,b,c,要用最少的操作把所有盘子从a柱子上转移到c柱子上。

输入样例:

3

输出样例:

move 1 from a to c
move 2 from a to b
move 1 from c to b
move 3 from a to c
move 1 from b to a
move 2 from b to c
move 1 from a to c

解题思路:

实现这个算法,可以简单分为以下三个步骤。

(1) 把第n-1个圆盘由a移到b。

(2) 把第n个圆盘由a移到c。

(3) 把第n-1个圆盘由b移到c。

从这里入手,加上上面数学问题解法的分析,不难发现,移动的步数必为奇数步。

(1) 第二步是把a柱子上剩下的一个盘子移到c柱子上。

(2) 第一步可以看成把a柱子上的n-1个圆盘借助c柱子移到b柱子上。

(3) 第三步可以看成把b上的n-1个圆盘借助a柱子移到c柱子上。

如3阶汉诺塔的移动: A→C,A→B,C→B,A→C,B→A,B→C,A→C。

参考程序:

#include <fstream>
#include <iostream>
using namespace std;
/ *将x柱子上编号为 t的圆盘移动到 柱子上 * /
void Move(int t,char x,char y) [cout<<"move "<<t<<" from "<<x<<" to "<<y<<endl;
/*将 n个圆盘从 a 柱子借助 b 柱子移到 c 柱子 * /
void Hannoi(int n,char a,char b,char c)
{if(n==1)
move(1,a,c)
Move(1,a,c); /* 若只有一个圆盘,则直接将该圆盘由 a 柱子移到 c 柱子 * /
else
{
Hannoi(n-1,a,c,b); / * 把 a 柱子上的 n-1个圆盘借助 c 柱子移到 b 柱子上* /
Move(n,a,c);  /*把 a 柱子上剩下的一个盘子移到 c 柱子上*/
Hannoi(n-1,b,a,c);  /*把b 柱子上的 n-1个圆盘借助 a 柱子移到 c 柱子上* /}
})int main()
int n;
scanf("%d",&n);
Hannoi(n,'a','b','c') ;
return 0;
}

02、木棒三角形

问题描述:

小A家里有很多长度不一的木棒,有一天他很无聊,摆弄这些木棒解闷。小A的数学学得很好,所以他想在这些木棒中挑出三根木棒组成一个直角三角形,当然,这可能有很多种选法,他还想挑出三根木棒组成一个面积最大的直角三角形。

输入:

输入有多组,每组输入包括两行,第一行输入一个n(0≤n≤100),表示小A有n根木棒,接着一行有n个整数(n≤1000),表示木棒的长度(长度从小到大给出)。

输出:

输出面积最大的直角三角形的面积,且保留3位小数,若不能组成,则输出“My Good!”。

输入数据:

4
1 2 3 4
5
2 3 4 5 6
6
3 4 5 6 8 10
2
1 1

输出数据:

My Good!
6.000
24.000
My Good!

解题思路:

看到题目很容易想到如果求出从n根木棒中选出三根木棒的所有情况的解,那答案也就出来了。

现在的主要问题是怎么用程序枚举所有情况。我们知道直角三角形的三条边中斜边是最长的,题目给出一个“长度从小到大给出”的条件,这样我们可以依次枚举三角形中长度最短、第二长和最长的边,具体实现代码如下。

参考程序:

#include< stdio.h>
#include<stdlib.h>
int main()
{
int i,j,k;
double ans;
int n;
int len[110];
while(scanf(rd",&n)!=EOF)
{for(i = 1;i <= n;i++)scanf("%d",&len[i]); //存储木棒长度
ans = -1;
for(i = l;i <= n;i++){  //枚举最短木棒
for(j = i+l;j <= n;j++){ //枚举第二长的木棒
for(k = j+1;k <= n;k++){  //枚举最长的木棒
if(len[i]*len[i] + len[j]*len[j] == len[k]* len[k]){ //如果是直角三角形
if(0.5*len[i]*len[j] > ans) //取最优解
ans = 0.5*len[i]*len[j];
}
}
}
}if(ans == -1)
printf("My Good! \n");
else
printf("%.3lf\n",ans);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系统安全测试要怎么做?

进行系统安全测试时&#xff0c;可以按照以下详细的步骤进行&#xff1a; 1、信息收集和分析&#xff1a; 收集系统的相关信息&#xff0c;包括架构、部署环境、使用的框架和技术等。 分析系统的安全需求、威胁模型和安全策略等文档。 2、威胁建模和风险评估&#xff1a; 使…

leetcode292. Nim 游戏(博弈论 - java)

Nim 游戏 Nim 游戏题目描述博弈论 上期经典算法 Nim 游戏 难度 - 简单 原题链接 - Nim游戏 题目描述 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。 你们轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xff0c;轮到的人拿掉 1 -…

494. 目标和

494. 目标和 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;数组回溯法动态规划 参考代码&#xff1a;数组回溯法__494目标和__动态规划 经验吸取 原题链接&#xff1a; 494. 目标和 https://leetcode.cn/problems/target-sum/description/ 完成情况&#…

Android进阶之多级列表

遇到一个需求需要显示多级列表&#xff0c;因为界面是在平板上的&#xff0c;所以层级是从左向右往下排的&#xff0c;类似于 我当时的写法是在xml布局里一个个RecyclerView往下排的 当然前提是已经规定好最大的层级我才敢如此去写界面&#xff0c;如果已经明确规定只有两级或…

69 # 强制缓存的配置

强制缓存 强制缓存&#xff1a;以后的请求都不需要访问服务器&#xff0c;状态码为 200协商缓存&#xff1a;每次都判断一下&#xff0c;告诉是否需要找缓存&#xff0c;状态码为 304 默认强制缓存&#xff0c;不缓存首页&#xff08;如果已经断网&#xff0c;那这个页面应该…

Python发送QQ邮件

使用Python的smtplib可以发送QQ邮件&#xff0c;代码如下 #!/usr/bin/python3 import smtplib from email.mime.text import MIMEText from email.header import Headersender 111qq.com # 发送邮箱 receivers [222qq.com] # 接收邮箱 auth_code "abc" # 授权…

Dockerfile概念、镜像原理、制作及案例讲解

1.Docker镜像原理 Linux文件操作系统讲解 2.镜像如何制作 3.Dockerfile概念 Docker网址&#xff1a;https://hub.docker.com 3.1 Dockerfile关键字 4.案例

【数据结构OJ题】链表分割

原题链接&#xff1a;https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId8&&tqId11004&rp2&ru/activity/oj&qru/ta/cracking-the-coding-interview/question-ranking 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2…

爬虫逆向实战(十七)--某某丁简历登录

一、数据接口分析 主页地址&#xff1a;某某丁简历 1、抓包 通过抓包可以发现数据接口是submit 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个enPassword加密参数 请求头是否加密&#xff1f; 通过查看请求头可以发现有一个To…

【面试高频题】难度 3/5,字典树热门运用题

题目描述 这是 LeetCode 上的 「745. 前缀和后缀搜索」 &#xff0c;难度为 「困难」。 Tag : 「字典树」 设计一个包含一些单词的特殊词典&#xff0c;并能够通过前缀和后缀来检索单词。 实现 WordFilter 类&#xff1a; WordFilter(string[] words) 使用词典中的单词 words 初…

无法将“环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称(pycharm)

无法将“配置的任何一个环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 记录解决“无法将“C:......conda.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称”以及“表达式或语句中包含意外的标记”的系列问题(VSCode开发环境)一、Conda.exe无法正常识…

【Java高级开发高频面试题】面试者角度的口述版

文章目录 1.具备扎实的Java基础集合HashMap底层工作原理HashMap版本问题HashMap并发修改异常HashMap影响HashMap性能的因素HashMap使用优化 SynchronizedThreadLocalAQS线程池JVM内存模型类加载机制与双亲委派垃圾回收算法、垃圾回收器、空间分配担保策略引用计数器算法、可达性…

创建 Web 内容目录

创建 Web 内容目录 按照下方所述&#xff0c;创建一个名为 /home/curtis/ansible/webcontent.yml 的 playbook &#xff1a; 该 playbook 在 dev 主机组中的受管节点上运行 创建符合下列要求的目录 /webdev &#xff1a; 所有者为 webdev 组 具有常规权限&#xff1a;ownerread…

Nginx反向代理

目录 一.简介1.反向代理 二.案例1.案例12.案例2 一.简介 1.反向代理 1.1反向代理&#xff1a; 是指代理服务器来接收Internet上的客户端请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;并将从服务器上得到的结果返回给客户端。此时代理服务器对外就表现为一…

循环队列的实现(c语言)

前言 循环队列是队列的一种特殊的结构&#xff0c;在生产者——消费者模型中常常使用它&#xff0c; 它在逻辑上是一个环形的连续的结构。在物理可以使用数组来实现。 目录 1.循环队列的逻辑结构 2.空的循环队列和满的循环队列 3.循环队列插入和删除 4.代码实现 …

音视频实时通话解决方案

1、问题提出 想要实现音视频通话,对于大部分人可能会觉得很难,但是实际上,有些事情并没有大家想的那样困难,只要功夫深,铁杵磨成针。 机缘巧合下,在业务中,我也遇到了一个业务场景需要实现音视频通话,我们不可能自己从零开始干,我本次用到的核心是WebRTC。 2、WebRT…

治疗偏头痛等亚疼痛的远程电神经调控(REN)设备

原文链接&#xff1a; NERIVIO CE标志适应症扩展到青少年和成人偏头痛的预防和急性治疗 (prnewswire.com) 公司官网&#xff1a; Homepage - Theranica APP下载链接&#xff1a; Migraine Headache Treatment - Nerivio 使用过程问题&#xff1a; 常见问题 - 无药物偏头痛两…

Flink状态和状态管理

1.什么是状态 官方定义&#xff1a;当前计算流程需要依赖到之前计算的结果&#xff0c;那么之前计算的结果就是状态。 这句话还是挺好理解的&#xff0c;状态不只存在于Flink&#xff0c;也存在生活的方方面面&#xff0c;比如看到一个认识的人&#xff0c;如何识别认识呢&am…

Python Web框架:Django、Flask和FastAPI巅峰对决

今天&#xff0c;我们将深入探讨Python Web框架的三巨头&#xff1a;Django、Flask和FastAPI。无论你是Python小白还是老司机&#xff0c;本文都会为你解惑&#xff0c;带你领略这三者的魅力。废话不多说&#xff0c;让我们开始这场终极对比&#xff01; Django&#xff1a;百…

web基础入门和php语言基础入门 二

web基础入门和php语言基础入门 二 MySQL入门-续MySQL之数据查询操作MySQL其他知识点 php语言基础入门认识PHPPHP的工作流程安装PHP环境认识一个PHP程序PHP基础知识点进入正题 PHP与WEB交互PHP与MySQL交互总结 MySQL入门-续 MySQL之数据查询操作 WHERE 子句&#xff0c;条件限…