秒懂算法 | 漢諾塔問題與木棒三角形

圖片

在數學與計算機科學中,遞歸(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.pswp.cn/news/41479.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41479.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41479.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android性能優化——線程優化

一、線程調度原理 在任意時刻&#xff0c;CPU只能執行一條指令&#xff0c;每個線程獲取到CPU的使用權之后才可以執行指令也就是說在任意時刻&#xff0c;只有一個線程占用CPU 處于運行狀態 多線程并發&#xff0c;實際上是指多個線程輪流獲取CPU 的使用權然后分別執行各自的任…

系統安全測試要怎么做?

進行系統安全測試時&#xff0c;可以按照以下詳細的步驟進行&#xff1a; 1、信息收集和分析&#xff1a; 收集系統的相關信息&#xff0c;包括架構、部署環境、使用的框架和技術等。 分析系統的安全需求、威脅模型和安全策略等文檔。 2、威脅建模和風險評估&#xff1a; 使…

調用被fishhook的原函數

OC類如果通過runtime被hook了&#xff0c;可以通過逆序遍歷方法列表的方式調用原方法。 那系統庫的C函數被fish hook了該怎么辦呢&#xff1f; 原理和OC類異曲同工&#xff0c;即通過系統函數dlopen()獲取動態庫&#xff0c;以動態庫為參數通過系統函數dlsym()即可獲取目標系統…

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…

AMD卡啟動Stable Diffusion AI繪畫的方法

WindowsAMD安裝法 1.安裝python 3.10.6&#xff0c;在python官網上下載安裝程序&#xff0c;***重要*** 在安裝的第一個窗口下方勾選“將python添加到path”。 2.安裝git 3.WindowsAMD使用AUTOMATIC1111的directml這一個fork&#xff0c;在這個頁面的第一段&#xff1a;https:/…

題目:2614.對角線上的質數

??題目來源&#xff1a; leetcode題目&#xff0c;網址&#xff1a;2614. 對角線上的質數 - 力扣&#xff08;LeetCode&#xff09; 解題思路&#xff1a; 遍歷對角線上的元素&#xff0c;返回最大的質數或 0 即可。 解題代碼&#xff1a; class Solution {public int dia…

e.target.value和 binding.value 區別

e.target.value 和 binding.value 都是在 Vue.js 中用于處理事件綁定時的值&#xff0c;但它們的使用場景和含義有所不同&#xff0c;分別用于普通的 DOM 事件和自定義指令。 e.target.value&#xff1a; 這是常用于原生 DOM 事件處理函數中的一個屬性&#xff0c;用于獲取事件…

爬蟲逆向實戰(十七)--某某丁簡歷登錄

一、數據接口分析 主頁地址&#xff1a;某某丁簡歷 1、抓包 通過抓包可以發現數據接口是submit 2、判斷是否有加密參數 請求參數是否加密&#xff1f; 通過查看“載荷”模塊可以發現有一個enPassword加密參數 請求頭是否加密&#xff1f; 通過查看請求頭可以發現有一個To…

【面試高頻題】難度 3/5,字典樹熱門運用題

題目描述 這是 LeetCode 上的 「745. 前綴和后綴搜索」 &#xff0c;難度為 「困難」。 Tag : 「字典樹」 設計一個包含一些單詞的特殊詞典&#xff0c;并能夠通過前綴和后綴來檢索單詞。 實現 WordFilter 類&#xff1a; WordFilter(string[] words) 使用詞典中的單詞 words 初…

單片機之從C語言基礎到專家編程 - 4 C語言基礎 - 4.9 變量與常量

基本數據類型可以作為變量與常量使用,顧名思義&#xff0c;變量運行時可以改變其值&#xff0c;常量運行時不會改變其值。 常量分為整型常量、浮點型常量、字符常量、字符串常量和符號常量。 通常用#define來定義一個標識符來表示一個常量 用type name 常量來定義一個變量,…

無法將“環境變量”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱(pycharm)

無法將“配置的任何一個環境變量”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。 記錄解決“無法將“C:......conda.exe”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱”以及“表達式或語句中包含意外的標記”的系列問題(VSCode開發環境)一、Conda.exe無法正常識…

ROS2 學習(三)話題

話題 節點之間的通信。 叫話題很形象。發布者發布一定數據類型的話題&#xff0c;訂閱者訂閱發布者。 訂閱者發布者不唯一。 異步通信&#xff0c;適用于周期發布的數據而不是邏輯性強的數據。 .msg 格式的消息結構&#xff0c;一種通信接口。 每個話題 topic 有話題名&a…

【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…