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. Oracle存储1.1

    1.生成一个表的简单sql语句 CREATE OR REPLACE PROCEDURE proc_AutoGenerateSQL(  tableName   VARCHAR2 ,--参数 需要操作的表 ...

  2. JavaScript--location.href的跳转

    页面重载 true 强制从服务器加载  false 优先从缓存加载  window.location.reload(true); window.location.href.self.location. ...

  3. mac Chrome 快捷键

    从windows迁移到mac,会发现快捷键真的变了,这里先吹一下mac OS天下第一 另外没有bar确实也提高了效率,这一点还是值的 其实程序员最常用的是检查,windows下是F12,默认F12会被 ...

  4. python第一天 :计算机基础(一)

    1.什么是编程语言 答:人类与计算机交流的介质 2.什么是编程 答:利用编程语言控制计算机解决问题 3.为什么要编程 答:可以控制计算机做事,提高生产生活效率 4.计算机的五大组成部分分别有什么作用? ...

  5. 如何用最暴力的方法改写Liferay的原生portlet

    最近在论坛上看到有人问如何改写Liferay原有的calendar portlet. 然后研究了一下,直接从portal中把calendar portlet的源码拷贝出来,然后修改再部署上去,但是这个 ...

  6. SSM+Maven+IDEA增删改查

    开发工具 IntelliJ IDEA Apache-tomcat-9.0 JDK 1.8 MySQL 8.0.11 Maven 3.5.4 IDEA+Maven搭建项目骨架 1. 新建Maven项目: ...

  7. php Laravel Thrift使用TMultiplexedProcessor复用端口模式

    thrift的使用中一般是一个Server对应一个Processor和一个Transport,如果有多个服务的话,那必须要启动多个Server,占用多个端口,这种方式显然不是我们想要的,所以thrif ...

  8. bzoj2073 PRZ

    Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍 ...

  9. NLP+2vec︱认识多种多样的2vec向量化模型

    1.word2vec 耳熟能详的NLP向量化模型. Paper: https://papers.nips.cc/paper/5021-distributed-representations-of-wo ...

  10. VS2017 打包成exe

    在项目的解决方案 右键→ 新建项目  后出现如下选择 (如果没有找到,请在联机中搜索  visual studio installer 并安装) 选择项目类型 Setup Project,并输入名称, ...