The Towers of Hanoi Revisited---(多柱汉诺塔)

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 <disc-radius> from <source-peg> to <target-peg>

if the disc is moved to the empty peg or

move <disc-radius> from <source-peg> to <target-peg> atop <target-top-disc-radius>

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
#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;
}
时间: 2024-10-15 23:44:05

The Towers of Hanoi Revisited---(多柱汉诺塔)的相关文章

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

传送门 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 puzz

多柱汉诺塔最优算法

转自Florian 1. 三柱汉诺塔三柱汉诺塔是经典的汉诺塔问题,在算法设计中是递归算法的典型问题.其算法是这样的: 首先把A 柱上面的n- 1 个碟子通过C 柱移到B 柱上[T(n-1)步],然后把A 柱剩下的一个碟子移到C 柱上[1步], 最后把B 柱上所有的碟子通过A 柱移到C 柱上[T(n-1)步].很容易得到算法的递归方程为:T(n)=2*T(n-1)+1,因此,不难算出步数是T(n)=2^n-1.对于三柱汉诺塔的算法的正确性自然是毫无争议的,我们需要的是从三柱汉诺塔的设计中引申出多柱

4柱汉诺塔(zz)

多柱汉诺塔可以用Frame–Stewart算法来解决. The Frame–Stewart algorithm, giving a presumably optimal solution for four (or even more) pegs, is described below: Let be the number of disks. Let be the number of pegs. Define to be the minimum number of moves required t

汉诺塔II(hdu1207)经典递推

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6070    Accepted Submission(s): 2966 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下

hd 1207(四汉诺塔)

三个汉诺塔算法 f(n)=2^n-1 两个思路大同小异 Frame算法 在1941年,一位名叫J. S. Frame的人在<美国数学月刊>上提出了一种解决四柱汉诺塔问题的算法,这是人们熟知的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)依据上

汉诺塔题目总结

参考了别人的代码的总结 1.四柱汉诺塔问题和n柱汉诺塔问题 题目: #include<cstdio> #include<algorithm> #include<cmath> using namespace std; double f[70]; void init() { f[1] = 1; f[2] = 3; for(int i = 3; i <= 65; i++) { double Max = f[i - 2] * 2 + 3; for(int j = 1; j

hdu1207 汉诺塔II (DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1207 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘.上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘.有预言说,这件事完成时宇

汉诺塔的问题:4个柱子,如果塔的个数变位a,b,c,d四个,现要将n个圆盘从a全部移到d,移动规则不变

四柱汉诺塔问题的求解程序.解题思路:如a,b,c,d四柱. 要把a柱第n个盘移到目标柱子(d柱),先把上层 分两为两部份,上半部份移到b柱,下半部分移到c柱,再把第n盘移到 目标柱子,然后,c柱盘子再移到目标柱子,再把b柱盘子移到目标柱子. 细节地方: 上半部份移到b柱时,它的中间变量柱子是有二选一的.而下半部分 移到c柱时,它的中间变量柱子只有一个(因为一个柱子已被上半部份 占了).b,c也移到目标柱子时同理.

SGU 202 The Towers of Hanoi Revisited (DFS+预处理)

题目描述: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2338 The Towers of Hanoi Revisited Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge You all must know the puzzle named ??The Towers of Hanoi??. The puzzle has thre