汉诺塔专题:P1760 通天之汉诺塔 题解 + Problem D: 汉诺塔 题解

1.  P1760 通天之汉诺塔 题解

题目背景

直达通天路·小A历险记第四篇

题目描述

在你的帮助下,小 A 成功收集到了宝贵的数据,他终于来到了传说中连接通天路的通天山。但是这距离通天路仍然有一段距离,但是小 A 突然发现他没有地图!!!但是幸运的是,他在山脚下发现了一个宝箱。根据经验判断(小 A 有经验吗?),地图应该就在其中!

在宝箱上,有三根柱子以及在一根柱子上的 n 个圆盘。小 A 在经过很长时间判断后,觉得这就是 hanoi 塔!(这都要琢磨)。但是移动是需要时间的,所以小 A 必须要通过制造延寿药水来完成这项任务。现在,他请你告诉他需要多少步完成,以便他造足够的延寿药水。

输入格式

一个数 n,表示有 n 个圆盘。

输出格式

一个数 s,表示需要 s 步。

输入输出样例

输入 #1

31

输出 #1

2147483647

输入 #2

15

输出 #2

32767

说明/提示

数据范围及约定

对于所有数据,n≤15000。

代码:

#include <iostream>
#include <vector>using namespace std;int main() {int n;cin >> n;vector<int> digits;digits.push_back(1); // 初始为1,逆序存储for (int i = 0; i < n; ++i) {int carry = 0;for (int j = 0; j < digits.size(); ++j) {int temp = digits[j] * 2 + carry;digits[j] = temp % 10;carry = temp / 10;}if (carry != 0) {digits.push_back(carry);}}// 减一操作int borrow = 1;for (int i = 0; i < digits.size() && borrow != 0; ++i) {digits[i] -= borrow;if (digits[i] < 0) {digits[i] += 10;borrow = 1;} else {borrow = 0;}}// 去除前导零while (!digits.empty() && digits.back() == 0) {digits.pop_back();}if (digits.empty()) {cout << 0;} else {for (auto it = digits.rbegin(); it != digits.rend(); ++it) {cout << *it;}}cout << endl;return 0;
}

代码解释:

代码逻辑分析

1. 输入处理
  • 读取整数 n,表示需要计算的次方数。
2. 初始化大数存储
  • 使用动态数组 digits ​​逆序存储​​大数,初始值为 [1]即 20=1)。
  • 逆序存储意味着低位在前,高位在后。例如,数值 123 存储为 [3, 2, 1]
3. 计算 2^n
  • 通过 ​​n 次循环​​,每次将当前数值乘以 2。
  • ​处理进位​​:
    • 遍历每一位数字,计算 当前位 × 2 + 进位
    • 更新当前位为结果的个位,进位为十位。
    • 若所有位处理完仍有进位,将其作为新高位加入数组。

​示例​​:初始为 1,计算 23=8:

  • 第1次循环:1×2 → 2 → [2]
  • 第2次循环:2×2 → 4 → [4]
  • 第3次循环:4×2 → 8 → [8]
4. 减一操作
  • 从最低位开始借位减一:
    • 若当前位减一后为负数,加 10 并设置借位。
    • 否则,直接减一并结束借位。

​示例​​:2^4=16 减一:

  • 数值 16 存储为 [6, 1]
  • 减一后,低位 6 → 5,无借位,结果为 [5, 1](即 15)。
5. 去除前导零
  • 逆序存储中前导零位于数组末尾,需移除。
  • 若所有位均为零,最终输出 0。
6. 输出结果
  • 逆序输出数组,得到正确的高位到低位顺序。

代码示例解析(以 n=3 为例)

  1. ​计算 2^3=8​​:
    • 初始 digits = [1]
    • 3次循环后,digits = [8](逆序存储 8)。
  2. ​减一​​:
    • 8 - 1 = 7 → digits = [7]
  3. ​输出​​:
    • 逆序输出 7

2. Problem D: 汉诺塔 题解

Description

        有三根柱A,B,C在柱A上有N块盘片,所有盘片都是大的在下面,小片能放在大片上面。现要将A上的N块片移到C柱上,每次只能移动一片,而且在同一根柱子上必须保持上面的盘片比下面的盘片小,请输出移动的步骤。

Input

        输入整数n,表示有n块盘片

Output

        输出移动的步骤

  • Sample Input

3

  • Sample Output
1 A->C
2 A->B
3 C->B
4 A->C
5 B->A
6 B->C
7 A->C
HINT

0 < n < 20

代码:

#include <cstdio>
#include <vector>
#include <string>
#include <cstring>using namespace std;vector<string> steps;
int step = 0;void hanoi(int n, char from, char to, char via) {if (n == 1) {step++;char buffer[20];snprintf(buffer, sizeof(buffer), "%d %c->%c", step, from, to);steps.emplace_back(buffer);} else {hanoi(n - 1, from, via, to);step++;char buffer[20];snprintf(buffer, sizeof(buffer), "%d %c->%c", step, from, to);steps.emplace_back(buffer);hanoi(n - 1, via, to, from);}
}int main() {int n;scanf("%d", &n);steps.reserve((1 << n) - 1); // 预分配足够内存hanoi(n, 'A', 'C', 'B');// 计算总输出长度size_t total_len = 0;for (const auto& s : steps) {total_len += s.size() + 1; // 每行加换行符}// 合并到缓冲区并一次性输出char* buffer = new char[total_len];char* ptr = buffer;for (const auto& s : steps) {size_t len = s.size();memcpy(ptr, s.c_str(), len);ptr += len;*ptr++ = '\n';}fwrite(buffer, 1, total_len, stdout);delete[] buffer;return 0;
}

代码解释:

  1. ​汉诺塔独特递归算法​​:

    • hanoi 函数递归地将 n 个盘子从起始柱 from 移动到目标柱 to,借助中间柱 via
    • 当 n=1 时,直接将盘子从 from 移到 to,记录步骤。
    • 对于 n>1,分解为三步:
      • 将 n-1 个盘子从 from 移至 via(递归调用)。
      • 将第 n 个盘子从 from 移至 to
      • 将 n-1 个盘子从 via 移至 to(递归调用)。
  2. ​记录步骤​​:

    • 使用全局变量 stepsvector<string>)存储每一步操作。
    • 每移动一个盘子,递增全局变量 step,并用 snprintf 格式化为字符串(如 "1 A->C")存入 steps
  3. ​性能优化​​:

    • ​内存预分配​​:steps.reserve((1 << n) - 1) 预分配足够内存,避免 vector 动态扩容的开销。
    • ​单次输出​​:计算所有步骤字符串的总长度,合并到连续内存缓冲区,通过 fwrite 一次性输出,减少频繁I/O操作的开销。
  4. ​代码结构​​:

    • ​全局变量​​:steps 和 step 简化参数传递,但在多线程环境中不安全(此处单线程无问题)。
    • ​递归实现​​:清晰体现汉诺塔问题分治思想,时间复杂度为 O(2ⁿ)。
    • ​输入输出​​:scanf 读取盘子数 n,高效输出避免逐行打印。

​总结​​:递归解决汉诺塔问题,记录每一步移动步骤,并通过内存预分配和单次输出优化性能,适合高效生成并输出大量步骤的场景。

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

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

相关文章

探索 HumanoidBench:类人机器人学习的新平台

在科技飞速发展的当下&#xff0c;类人机器人逐渐走进我们的视野&#xff0c;它们有着和人类相似的外形&#xff0c;看起来能像人类一样在各种环境里完成复杂任务&#xff0c;潜力巨大。但实际上&#xff0c;让类人机器人真正发挥出实力&#xff0c;还面临着重重挑战。 这篇文…

数据结构中的宝藏秘籍之广义表

广义表&#xff0c;也被称作列表&#xff08;Lists&#xff09;&#xff0c;是一种递归的数据结构。它就像一个神秘的盒子&#xff0c;既可以装着单个元素&#xff08;原子&#xff09;&#xff0c;也可以嵌套着其他的盒子&#xff08;子列表&#xff09;。比如广义表 (a (b c)…

【jenkins】首次配置jenkins

第一步&#xff0c;输入管理员密码 cat /var/jenkins_home/secrets/initialAdminPassword第二步&#xff0c;点击安装推荐的插件 第三步&#xff0c;创建管理员用户 第四步&#xff0c;返回实例 第五步&#xff0c; 升级jenkins 第六步&#xff0c; 修复提示 第七步&#xff0c…

Android studio—socketIO库return与emit的使用

文章目录 一、Socket.IO库简单使用说明1. 后端 Flask Flask-SocketIO2. Android 客户端集成 Socket.IO3. 布局文件注意事项 二、接受服务器消息的二种方法1. 客户端接收通过 emit 发送的消息功能使用场景后端代码&#xff08;Flask-SocketIO&#xff09;客户端代码&#xff08…

用Prompt 技术【提示词】打造自己的大语言智能体

机器如何按照人类的指令执行任务的探索 机器需具备理解任务叙述的能力&#xff0c;以便能够按照人类的指令执行任务&#xff0c;为机器提供一些范例作为参考&#xff0c;使其能够理解该执行的任务类型。这样的学习方式称为“Instruction learning”&#xff0c;透过精心设计的…

Node.js 数据库 事务 项目示例

1、参考&#xff1a;JavaScript语言的事务管理_js 函数 事务性-CSDN博客 或者百度搜索&#xff1a;Nodejs控制事务&#xff0c; 2、实践 2.1、对于MySQL或MariaDB&#xff0c;你可以使用mysql或mysql2库&#xff0c;并结合Promise或async/await语法来控制事务。 使用 mysql2…

【Mamba】MambaVision论文阅读

文章目录 MambaVision一、研究背景&#xff08;一&#xff09;Transformer vs Mamba​&#xff08;二&#xff09;Mamba in CV​ 二、相关工作​&#xff08;一&#xff09;Transformer 在计算机视觉领域的进展​&#xff08;二&#xff09;Mamba 在计算机视觉领域的探索​ 三、…

前端面试宝典---原型链

引言----感谢大佬的讲解 大佬链接 原型链示意图 原型链问题中需要记住一句话&#xff1a;一切变量和函数都可以并且只能通过__proto__去找它所在原型链上的属性与方法 原型链需要注意的点 看上图可以发现 函数&#xff08;构造函数&#xff09;也可以通过__proto__去找到原…

C语言---FILE结构体

一、FILE 结构体的本质与定义 基本概念 FILE 是 C 语言标准库中用于封装文件操作的结构体类型&#xff0c;定义于 <stdio.h> 中。它代表一个“文件流”&#xff0c;可以是磁盘文件、标准输入输出&#xff08;stdin/stdout/stderr&#xff09;或其他输入输出设备。 实现特…

基于大模型的直肠息肉诊疗全流程风险预测与方案优化研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、大模型技术概述 2.1 大模型原理简介 2.2 大模型在医疗领域应用现状 三、直肠息肉术前预测与准备 3.1 基于大模型的术前风险预测 3.1.1 息肉性质预测 3.1.2 手术难度预测 3.2 基于预测结果的术前准备 3.…

华为OD机试真题——MELON的难题(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《MELON的…

AI数据分析与BI可视化结合:解锁企业决策新境界

大家好&#xff0c;今天我们来聊聊一个前沿而热门的话题——AI数据分析与BI可视化结合&#xff0c;如何携手推动企业决策迈向新高度。在数据爆炸的时代&#xff0c;企业如何高效利用这些数据&#xff0c;成为制胜的关键。AI数据分析与BI可视化的结合&#xff0c;正是解锁这一潜…

克服储能领域的数据处理瓶颈及AI拓展

对于储能研究人员来说&#xff0c;日常工作中经常围绕着一项核心但有时令人沮丧的任务&#xff1a;处理实验数据。从电池循环仪的嗡嗡声到包含电压和电流读数的大量电子表格&#xff0c;研究人员的大量时间都花在了提取有意义的见解上。长期以来&#xff0c;该领域一直受到对专…

【SpringBoot+Vue自学笔记】002 SpringBoot快速上手

跟着这位老师学习的&#xff1a;https://www.bilibili.com/video/BV1nV4y1s7ZN?vd_sourceaf46ae3e8740f44ad87ced5536fc1a45 最好和老师的idea版本完全一致&#xff01;截至本文写的当日最新的idea好像默认jdk17&#xff0c;配置时遇到很多bug。 &#x1f33f; Spring Boot&a…

SpringAI+DeepSeek大模型应用开发——2 大模型应用开发架构

目录 2.大模型开发 2.1 模型部署 2.1.1 云服务-开放大模型API 2.1.2 本地部署 搜索模型 运行大模型 2.2 调用大模型 接口说明 提示词角色 ​编辑 会话记忆问题 2.3 大模型应用开发架构 2.3.1 技术架构 纯Prompt模式 FunctionCalling RAG检索增强 Fine-tuning …

蓝桥杯12. 日期问题

日期问题 原题目链接 题目描述 小明正在整理一批历史文献。这些历史文献中出现了很多日期。 小明知道这些日期都在 1960 年 1 月 1 日 至 2059 年 12 月 31 日 之间。 令小明头疼的是&#xff0c;这些日期采用的格式非常不统一&#xff1a; 有的采用 年/月/日有的采用 月…

STM32使用rand()生成随机数并显示波形

一、随机数生成 1、加入头文件&#xff1a;#include "stdlib.h" 2、定义一个用作生成随机数种子的变量并加入到滴答定时器中不断自增&#xff1a;uint32_t run_times 0; 3、设置种子&#xff1a;srand(run_times);//每次生成随机数前调用一次为佳 4、生成一个随…

『前端样式分享』联系我们卡片式布局 自适应屏幕 hover动效 在wikijs中使用 (代码拿来即用)

目录 预览效果分析要点响应式网格布局卡片样式&#xff1a;阴影和过渡效果 代码优化希望 长短不一的邮箱地址在左右居中的同时,做到左侧文字对齐(wikijs可用)总结 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中…

【ubuntu】在Linux Yocto的基础上去适配Ubuntu的wifi模块

一、修改wifi的节点名 1.找到wifi模块的PID和VID ifconfig查看wifi模块网络节点的名字&#xff0c;发现是wlx44876393bb3a&#xff08;wlxmac地址&#xff09; 通过udevadm info -a /sys/class/net/wlx44876393bba路径的命令去查看wlx44876393bba的总线号&#xff0c;端口号…

健康养生:开启活力生活新篇章

在当代社会&#xff0c;熬夜加班、久坐不动、外卖快餐成为许多人的生活常态&#xff0c;随之而来的是各种亚健康问题。想要摆脱身体的疲惫与不适&#xff0c;健康养生迫在眉睫&#xff0c;它是重获活力、拥抱美好生活的关键。​ 应对不良饮食习惯带来的健康隐患&#xff0c;饮…