关闭

Acdream 1219 The Towers of Hanoi Revisited(递归汉诺塔问题)

标签: 递归问题
2845人阅读 评论(0) 收藏 举报
分类:

传送门

The Towers of Hanoi Revisited
Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Submit Statistic Next Problem
Problem Description

  You all must know the puzzle named "The Towers of Hanoi". The puzzle has three pegs and N discs of different radii, initially all disks are located on the first peg, ordered by their radii - the largest at the bottom, the smallest at the top. In a turn you may take the topmost disc from any peg and move it to another peg, the only rule says that you may not place the disc atop any smaller disk. The problem is to move all disks to the last peg making the smallest possible number of moves.
  There is the legend that somewhere in Tibet there is a monastery where monks tirelessly move disks from peg to peg solving the puzzle for 64 discs. The legend says that when they finish, the end of the world would come. Since it is well known that to solve the puzzle you need to make 2N - 1 moves, a small calculation shows that the world seems to be a quite safe place for a while.
  However, recent archeologists discoveries have shown that the things can be a bit worse. The manuscript found in Tibet mountains says that the puzzle the monks are solving has not 3 but M pegs. This is the problem, because when increasing the number of pegs, the number of moves needed to move all discs from the first peg to the last one following the rules described, decreases dramatically. Calculate how many moves one needs to move N discs from the first peg to the last one when the puzzle has M pegs and provide the scenario for moving the discs.

Input

  Input file contains N and M (1 ≤ N ≤ 64, 4 ≤ M ≤ 65).

Output

  On the first line output L - the number of moves needed to solve the puzzle. Next L lines must contain the moves themselves. For each move print the line of the form

move from to
if the disc is moved to the empty peg or
move from to atop
if the disc is moved atop some other disc.
Disc radii are integer numbers from 1 to N, pegs are numbered from 1 to M.
Sample Input

5 4
Sample Output

13
move 1 from 1 to 3
move 2 from 1 to 2
move 1 from 3 to 2 atop 2
move 3 from 1 to 4
move 4 from 1 to 3
move 3 from 4 to 3 atop 4
move 5 from 1 to 4
move 3 from 3 to 1
move 4 from 3 to 4 atop 5
move 3 from 1 to 4 atop 4
move 1 from 2 to 1
move 2 from 2 to 4 atop 3
move 1 from 1 to 4 atop 2

题目大意:
就是给你N个盘子,M个柱子,让你求的是怎么样操作使第一个柱子上的全部的盘子移动到最后一个盘子,操作数目最少并将移动的方法写出来。
解题思路:
在这路首先介绍一个算法—Frame算法(这是四柱汉诺塔问题):
(1)用4柱汉诺塔算法把A柱上部分的n- r个碟子通过C柱和D柱移到B柱上【F( n- r )步】。
(2)用3柱汉诺塔经典算法把A柱上剩余的r个碟子通过C柱移到D柱上【2^r-1步】。
(3)用4柱汉诺塔算法把B柱上的n-r个碟子通过A柱和C柱移到D柱上【F(n-r)步】。
(4)依据上边规则求出所有r(1≤r≤n)情况下步数f(n),取最小值得最终解。

因此Frame算法的递归方程如下:
F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n)。
通过这个方程我们能得到所有4柱汉诺塔的步骤个数,同时也有人证明[1]了,对于四柱汉诺塔,当

r=((8n+1)1)/2
时,能保证f(n)取得最小值
F(n)=(n(r2r+2)/2)2r+1
。所以算法的复杂度是
F(n)=O((2n)2(2n))
。从这这个方程中也可以看出,在n<6的时候,我们可以验证是和我们起初的构想的结构是相同的,但是当n再增多时就不是当初想的那样了。
接下来就是根据四柱的Frame算法来求解M柱的问题
(1)用M柱汉诺塔算法把1柱上部分的n-r个碟子通过3…M柱移到2柱上【M( n- r )步】。
(2)用M-1柱汉诺塔算法把1柱上剩余的r个碟子通过3…M-1柱移到M柱上【(r)步】。
(3)用M柱汉诺塔算法把2柱上的n-r个碟子通过1柱和3…M柱移到M柱上【M( n- r )步】。
(4)依据上边规则求出所有r(1≤r≤n)情况下步数m(n),取最小值得最终解M(n)。
其实我们的这个问题就是基于这个算法求解的就是一个递归的问题:
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1e2+5;
const double eps = 1e-9;
const int INF = 1e8+5;
int f[MAXN][MAXN], p[MAXN][MAXN];///f:步数 p:节点
void get(int n, int k)
{
    if(f[n][k] != -1)
        return;
    f[n][k] = INF;
    if(k < 3)
        return;
    for(int m=1; m<n; m++)
    {
        get(m, k);
        get(n-m, k-1);
        int tp = 2*f[m][k]+f[n-m][k-1];
        if(f[n][k] > tp)
        {
            f[n][k] = tp;
            p[n][k] = m;
        }
    }
}
int n, m;
int hanoi[MAXN][MAXN], num[MAXN];
void print(int s, int t, int a, int b)
{
    if(a == 1)
    {
        printf("move %d from %d to %d ",hanoi[s][num[s]]+1,s,t);
        if(num[t])
            printf("atop %d",hanoi[t][num[t]]+1);
        puts("");
        num[t]++;
        hanoi[t][num[t]]=hanoi[s][num[s]--];
        return;
    }
    for(int i=1; i<=m; i++)
    {
        if(i!=s && i!=t)
        {
            if(hanoi[i][num[i]] > hanoi[s][num[s]-p[a][b]+1])
            {
                print(s, i, p[a][b], b);
                print(s, t, a-p[a][b], b-1);
                print(i, t, p[a][b], b);
                return;
            }
        }
    }
    return ;
}
int main()
{
    while(cin>>n>>m)
    {
        memset(f, -1, sizeof(f));
        for(int i=1; i<=m; i++)
            f[1][i] = 1;
        get(n, m);
        cout<<f[n][m]<<endl;
        memset(hanoi, 0, sizeof(hanoi));
        memset(num, 0, sizeof(num));
        for(int i=n; i>=1; i--)
        {
            hanoi[1][num[1]] = i;
            num[1]++;
        }
        for(int i=1; i<=m; i++)
            hanoi[i][0] = INF;
        print(1, m, n, m);
    }
    return 0;
}
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

汉诺塔(Tower of Hanoi)问题的求解——利用栈与递归

汉诺塔(Tower of Hanoi)问题的求解——利用栈与递归 1. 汉诺塔问题的提法 汉诺塔问题是使用递归解决问题的经典范例。 传说婆罗门庙里有一个塔台,台上有3根标号为A、B、C的用钻石做成...
  • cainv89
  • cainv89
  • 2016-05-22 23:32
  • 6468

深入理解递归以及汉诺塔问题[数据结构]

一.深入理解递归1.什么是递归?递归就是一个函数直接或者间接的调用自己。2.函数是如何完成调用的?2.1主调函数调用被调函数前,要做3件事1.主调函数将所有的实参、返回地址传递给被调函数 2.为被调...
  • u011509781
  • u011509781
  • 2016-01-29 09:51
  • 340

用递归法:设计算法求解汉诺塔问题,并编程实现。 (1) Hanoi(汉诺)塔问题分析 这是一个古典的数学问题,是一个用递归方法解题的典型例子。问题是这样的:古代有一个梵塔,塔内有3个座 A,B,C

用 递归法:设计算法求解汉诺塔问题,并编程实现。 (1) Hanoi(汉诺)塔问题分析 这是一个古典的数学问题,是一个用递归方法解题的典型例子。问题是这样的:古代有一个梵塔,塔内有3个座 A,B,...
  • u011329762
  • u011329762
  • 2014-11-11 18:31
  • 7215

n阶汉诺塔盘问题(Hanoi)

n阶汉诺塔盘问题
  • lvdezhou
  • lvdezhou
  • 2015-12-11 13:32
  • 714

汉诺塔问题是使用递归解决问题的经典范例。

汉诺塔问题是使用递归解决问题的经典范例。   汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上(如图)。有一个和尚想把这64...
  • yangting09032214
  • yangting09032214
  • 2015-09-21 21:12
  • 940

hanoi汉诺塔问题

Hanoi塔问题是个古典的数学问题,如果能够想清楚这个问题,那我相信你的逻辑思维已经很不错了,问题是这样的: 古代有一个梵塔,塔内三个座A,B,C,A上有64个盘子,从小到大,从上而下依次排列,有人想...
  • wl1411956542
  • wl1411956542
  • 2016-09-26 22:15
  • 279

Hanoi汉诺塔问题

Hanoi汉诺塔 汉诺塔问题: 设A,B,C是三个塔座。开始时,在塔座a上有一叠共n个圆盘,这些圆盘自上到下,由大到小地叠放在一起。现要求将塔座A上的这一叠圆盘移动到塔座C上 ( 可以借助...
  • cassiePython
  • cassiePython
  • 2015-09-02 22:31
  • 639

(原创)Hanoi塔问题的递归方法与非递归方法(java实现)

本文讨论了Hanoi塔问题的递归方法与非递归方法,给出了java实现的代码,并比较了它们的效率。
  • JeCode
  • JeCode
  • 2015-11-18 00:13
  • 3016

汉诺塔递归方法和非递归方法

三个盘子为A,B,C,其中C是中介盘,我们要遵守移动规则将A上的盘子要全部通过B移动到C。#include #include using namespace std; #define MaxSize ...
  • sinat_37718529
  • sinat_37718529
  • 2017-11-22 17:02
  • 67

双色汉诺塔问题

//双色汉诺塔问题 #include using namespace std; int removeTimes = 0; void hanoiorignal(int nmovnum, char cz...
  • firechungelaile
  • firechungelaile
  • 2014-09-29 22:19
  • 2274
    个人资料
    • 访问:509083次
    • 积分:11344
    • 等级:
    • 排名:第1597名
    • 原创:639篇
    • 转载:5篇
    • 译文:0篇
    • 评论:93条
    博客专栏