zoj 2338 The Towers of Hanoi Revisited
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的更多相关文章
- ZOJ-2338 The Towers of Hanoi Revisited 输出汉诺塔的最优解移动过程
题意:给定N(1<= N <=64)个盘子和M(4<= M <= 65)根柱子,问把N个盘子从1号柱子移动到M号柱子所需要的最少步数,并且输出移动过程. 分析:设f[i][j] ...
- SGU 202 The Towers of Hanoi Revisited (DP+递归)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意 :n个圆盘,m个柱子的汉诺塔输出步骤. ht ...
- SGU 202. The Towers of Hanoi Revisited
多柱汉诺塔问题. 引用自wiki百科 多塔汉诺塔问题 在有3个柱子时,所需步数的公式较简单,但对于4个以上柱子的汉诺塔尚未得到通用公式,但有一递归公式(未得到证明,但目前为止没有找到反例): 令为在有 ...
- The Towers of Hanoi Revisited---(多柱汉诺塔)
Description You all must know the puzzle named "The Towers of Hanoi". The puzzle has three ...
- [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 ...
- 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 ...
- POJ 1958 Strange Towers of Hanoi
Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3784 Accepted: 23 ...
- POJ-1958 Strange Towers of Hanoi(线性动规)
Strange Towers of Hanoi Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 2677 Accepted: 17 ...
- ural 2029 Towers of Hanoi Strike Back (数学找规律)
ural 2029 Towers of Hanoi Strike Back 链接:http://acm.timus.ru/problem.aspx?space=1&num=2029 题意:汉诺 ...
随机推荐
- new操作符实现过程
var obj = new Object(); //创建新对象 一. new是干嘛的? new操作符用来生成一个新的对象, 它后面必须跟上一个函数(否则, 会抛出TypeError异常), 这个函数就 ...
- web前端学习(四)JavaScript学习笔记部分(5)-- 事件流详解
1.JS事件详解-事件流 1.1.事件流 1.事件流: 描述的是在页面中接受事件的顺序 2.事件冒泡: 由最具体的元素接收,然后逐级上传播至最不具体的节点(文档) 3.事件捕获: 最不具体的节点先接收 ...
- oracle包头包体
补充说明:包头和包体可以以java的接口来理解,包头像java的接口,包体像java接口的实现类. 一 包的组成 包头(package):包头部分申明包内数据类型,常量,变量,游标,子程序和异常错误处 ...
- 2019-8-31-dotnet-core-用值初始化整个数组
title author date CreateTime categories dotnet core 用值初始化整个数组 lindexi 2019-08-31 16:55:58 +0800 2019 ...
- Python之常用模块1
1.time datetime模块 #_*_coding:utf-8_*_ __author__ = 'Alex Li' import time # print(time.clock()) #返回处理 ...
- golang数据类型二
字符类型 3.14基本数据类型的相互转换 3.15基本数据类型和string的转换 FormatInt // FormatUint 将 int 型整数 i 转换为字符串形式// base:进位制(2 ...
- linux包之包管理rpm-yum
背景 YUM(Yellow dog Updater, Modified)为多个Linux发行版的前端软件包管理器,例如 Redhat RHEL, CentOS & Fedora. YUM通过调 ...
- CC2540 / CC2541 竟然支持 Bluetooth BLE 5.0?
CC2540 / CC2541 竟然支持 Bluetooth BLE 5.0? 无意中发现 CC2541 的 BLE 协议栈更新了. BLE-STACK is Bluetooth 5.0 qualif ...
- Uva 10446【递推,dp】
UVa 10446 求(n,bcak)递归次数.自己推出来了一个式子: 其实就是这个式子,但是不知道该怎么写,怕递归写法超时.其实直接递推就好,边界条件易得C(0,back)=1.C(1,back)= ...
- 关于取List中的指定几条数据以及注意事项
list1 = list2.subList(start, end); start,end分别是第几个到第几个. 注意的是此方法和substring一样,包含前不包含结尾,取下标索引 另一个注意的地方是 ...