遞歸方法解決漢諾塔問題(舉例說明)

遞歸方法解決漢諾塔問題(舉例說明)

問題描述
有三根杆左中右( left,mid , right ),在其中一杆( from )自下而上、由大到小按順序放置num個金盤。遊戲的目標:把該杆的金盤( from )全部移到另一杆 (to) 上,並仍保持原有順序疊好。
操作規則:每次只能移動一個盤子,並且在移動過程中三根杆上都始終保持大盤在下,小盤在上。
如圖:將左邊杆子上num個圓盤移到右邊杆子上。
由上到下爲1, 2 ,3, … ,num-1, num個盤子在這裏插入圖片描述
在這裏插入圖片描述
舉例
from爲left, to爲mid,num爲3. (即從左邊移動三個盤子到中間)
移動方法:
move 1 from left to mid
move 2 from left to right
move 1 from mid to right
move 3 from left to mid
move 1 from right to left
move 2 from right to mid
move 1 from left to mid
遞歸方法
遞歸頭(遞歸的最底層):當num剩一個時直接將這一個移到目標to杆子上,然後返回。
遞歸體:有from(起始杆)和to(終止杆),設另一個杆子爲another,將num-1個圓盤從from移到another,再將剩餘一個最大的圓盤num移到to,最後將num-1個圓盤移到to…
輸入以及輸出
輸入移動盤子數量num,以及起始杆from和目標杆to;
輸出移動方法和移動次數。
參考代碼

import java.util.Scanner;
public class HanNuoTa {
 public static void main(String[] args) {
  Scanner cs = new Scanner(System.in);
  System.out.print("盤子個數: "); 
  int num =cs.nextInt();           //輸入盤子個數
  System.out.print("起始位置: ");
  String from = cs.next();         //輸入起始杆,from,mid 或 right
  System.out.print("終止位置: ");
  String to = cs.next();           //輸入目標杆,from,mid 或 right
  System.out.println(Pro(num,"left","mid","right",from,to));
  
 }
  static int Pro(int num, String left, String mid, String right, String from, String to) {
  if(num<1) return 0;
  else return process(num,left,mid,right,from,to);
  }
  static int process(int num, String left, String mid, String right, String from, String to) {
   if(num==1) {
    System.out.println("move "+ num +" from "+ from +" to "+ to);
    return 1;  //返回移動次數
   }
   //下面爲遞歸體,先要找到除from和to的另一個杆子
   //我分爲兩步去找,如果from和to有一個是mid杆子,則另一個杆子不是left就是right
   //否則,另一個杆子就是mid
   //然後開始移動
   if(from.equals(mid)||to.equals(mid)) {
    String another = (from.equals(left)||to.equals(left))?right:left;
    //找到另一個杆子another
    int part1 = process(num-1,left,mid,right,from,another);
    //將num-1個圓盤從from移到another
    int part2 = 1;
    System.out.println("move "+ num +" from "+ from +" to "+ mid);
    //將剩餘一個最大的圓盤num移到to
    int part3 = process(num-1,left,mid,right,another,to);
    //最後將num-1個圓盤從another移到to
    return part1+part2+part3;  //返回移動次數
   }
   else { 
    //此時另一個圓盤就是mid
    int part1 = process(num-1,left,mid,right,from,mid);
    int part2 = 1;
    System.out.println("move "+ num +" from "+ from +" to "+ to);
    int part3 = process(num-1,left,mid,right,mid,to);
    return part1+part2+part3;
   }
  }
}

運行
在這裏插入圖片描述
思考
現修改遊戲規則:現在限制不能從最左側的塔直接移動到最右側,也不能從最右側直接移動到最左側,而是必須經過中間。求當塔有N層的時候,打印最優移動過程和最優移動總步數。(點擊這裏查看

個人學習經驗總結,如有問題,歡迎指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章