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 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.

This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.

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

1

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

汉诺塔问题,了解一个公式。记f[n][m]为n个disc,m个peg的Hanoi问题,则有dp公式f[n][m]=min{f[n-k][m-1]+2*f[k][m]}。即把上面的k个disc利用m个peg转移某个中间peg,再把下面的n-k个disc利用m-1个peg转移到目标peg,最后把上面的k个disc利用m个peg移到目标peg。dp过程记下使得f[n][m]最小的g[n][m]=k用于反向打印移动过程。

题意:给定N(1<= N <=64)个盘子和M(4<= M <= 65)根柱子,问把N个盘子从1号柱子移动到M号柱子所需要的最少步数,并且输出移动过程。

附上代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std; typedef unsigned long long ll;
const ll INF=;
ll dp[][];
int pre[][];
int n,m;
stack<int>v[];
bool w[]; void move(int a,int b) //从a这根柱子移到b这跟柱子
{
if(v[b].empty()) printf("move %d from %d to %d\n",v[a].top(),a,b);
else printf("move %d from %d to %d atop %d\n",v[a].top(),a,b,v[b].top());
v[b].push(v[a].top());
v[a].pop();
return;
} void DFS(int ct,int a,int b,int h) //ct 表示盘子个数 a,b表示柱子标号 通过h根的柱子来进行操作
{
int i,j;
if(ct==)
{
move(a,b);
return;
}
for(i=; i<=m; i++)
if(i!=a && i!=b && !w[i]) break;
DFS(pre[ct][h],a,i,h);
w[i]=;
DFS(ct-pre[ct][h],a,b,h-);
w[i]=;
DFS(pre[ct][h],i,b,h);
} void init()
{
int i,j,k;
for(i=; i<=; i++) //最少三根柱子,才可以开始移动,从这里开始记录数据
{
dp[i][]=*dp[i-][]+;
pre[i][]=i-;
}
for(i=; i<=; i++) //柱子
{
dp[][i]=;
for(j=; j<; j++) //盘子
{
ll t=INF;
for(k=; k<j; k++) //先移走k个盘子到一个中间柱子,剩下j-k盘子移动到目标
{
if(t>dp[j-k][i-]+*dp[k][i])
{
t=dp[j-k][i-]+*dp[k][i];
pre[j][i]=k;
}
}
dp[j][i]=t;
}
}
} int main()
{
int i,j,T;
init();
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",dp[n][m]);
for(i=; i<=m; i++) while(!v[i].empty()) v[i].pop(); //初始数据为空
for(i=n; i>=; i--) v[].push(i);
memset(w,,sizeof(w));
DFS(n,,m,m);
}
return ;
}

zoj 2338 The Towers of Hanoi Revisited的更多相关文章

  1. ZOJ-2338 The Towers of Hanoi Revisited 输出汉诺塔的最优解移动过程

    题意:给定N(1<= N <=64)个盘子和M(4<= M <= 65)根柱子,问把N个盘子从1号柱子移动到M号柱子所需要的最少步数,并且输出移动过程. 分析:设f[i][j] ...

  2. SGU 202 The Towers of Hanoi Revisited (DP+递归)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意 :n个圆盘,m个柱子的汉诺塔输出步骤. ht ...

  3. SGU 202. The Towers of Hanoi Revisited

    多柱汉诺塔问题. 引用自wiki百科 多塔汉诺塔问题 在有3个柱子时,所需步数的公式较简单,但对于4个以上柱子的汉诺塔尚未得到通用公式,但有一递归公式(未得到证明,但目前为止没有找到反例): 令为在有 ...

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

    Description You all must know the puzzle named "The Towers of Hanoi". The puzzle has three ...

  5. [CareerCup] 3.4 Towers of Hanoi 汉诺塔

    3.4 In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different sizes ...

  6. POJ 1958 Strange Towers of Hanoi 解题报告

    Strange Towers of Hanoi 大体意思是要求\(n\)盘4的的hanoi tower问题. 总所周知,\(n\)盘3塔有递推公式\(d[i]=dp[i-1]*2+1\) 令\(f[i ...

  7. POJ 1958 Strange Towers of Hanoi

    Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3784 Accepted: 23 ...

  8. POJ-1958 Strange Towers of Hanoi(线性动规)

    Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 2677 Accepted: 17 ...

  9. ural 2029 Towers of Hanoi Strike Back (数学找规律)

    ural 2029 Towers of Hanoi Strike Back 链接:http://acm.timus.ru/problem.aspx?space=1&num=2029 题意:汉诺 ...

随机推荐

  1. 二维vector基本使用

    变量声明 vector<vector<int> > 变量名: 添加行 vector<vector<int> > v2d; for(int i=0;i&l ...

  2. 第八章—BOM(一)

    ECMAscript是JS的核心,而要在web上使用JS,那么BOM无疑是真正的核心.BOM叫浏览器对象模型,它提供了许多对象,用于访问浏览器的功能. BOM的核心对象是window,它表示浏览器的一 ...

  3. php 7.2 安装 mcrypt 扩展

    升级 php 7.2 后,使用微信提供的加解密代码时,提示 call to undefined function mcrypt_module_open() :大脑疯狂运转1秒钟后,得出结论:php 7 ...

  4. 手机端点击键盘无法获取keyCode值的部分时隐藏键盘并执行事件

    用计时器监视window.innerHeight高度改变来判断.触发键盘其他地方也有事件反应 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

  5. Linux下下载安装jdk1.7和IDEA

    一.安装JDK1.7 准备: 到Oracle官网下载下载jdk1.7,参考博客 https://blog.csdn.net/H12KJGJ/article/details/79240984 官网地址: ...

  6. Django创建对象的create和save方法

    Django的模型(Model)的本质是类,并不是一个具体的对象(Object).当你设计好模型后,你就可以对Model进行实例化从而创建一个一个具体的对象.Django对于创建对象提供了2种不同的s ...

  7. JSP Web第三章整理复习 开发环境搭建

    P86  WEB工作原理 用户使用浏览器通过HTTP协议请求服务器上的Web资源,服务器接收到该请求后,读取请求的URI所标识的资源,加上其他资源发送给客户端的浏览器,浏览器解析响应中的HTML数据, ...

  8. Neo4j学习笔记(1)——使用Java API实现简单的增删改查

    阅读目录 项目的创建及配置 使用嵌入式数据库 创建节点和关系 查询及更新 删除关系和节点 完整代码 参考资料 回到顶部 项目的创建及配置 因为Neo4j依赖的jar包比较多,所以推荐使用Maven来管 ...

  9. Directx11教程(16) D3D11管线(5)

    原文:Directx11教程(16) D3D11管线(5) 本章我们学习VS中具体做些什么事情? 首先再看看我们的VS shader代码: Clolor.vs - PixelInputType Col ...

  10. Seata 0.7.0 正式发布

    Seata 是 阿里巴巴 开源的 分布式事务中间件,以 高效 并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题.Seata 0.7.0 已正式发布,本次共合并59pr,主要包括: ...