zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    聊聊面试-NoClassDefFoundError 和 ClassNotFoundException 区别
    聊聊面试-int和Integer的区别
    数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)
    SQL Server数据库阻塞,死锁查询
    数据误操作,教你使用ApexSQLLog工具从 SQLServer日志恢复数据!
    IDEA将Maven项目中指定文件夹下的xml等文件编译进classes
    Tomcat 中文乱码,设置UTF-8
    C#实现前向最大匹、字典树(分词、检索)
    23种设计模式汇总
    Head First设计模式——原型模式和访问者模式
  • 原文地址:https://www.cnblogs.com/chen9510/p/5539311.html
Copyright © 2011-2022 走看看