【汉诺塔问题】ural1054

1054. Hanoi Tower

Time limit: 1.0 second
Memory limit: 64 MB

Background

"Hanoi tower" puzzle is well known. There are 3 pegs with numbers: #1, #2 and #3.  N disks of different diameters are set on the first peg in the following order: the lower disk is set, the larger diameter it has. Your aim is to move all disks onto the second peg using the peg #3 as an auxiliary one. Following the rules within a move it's allowed to replace only one uppermost disk. Besides it's forbidden to put the disk of the bigger diameter onto the disk of the smaller one.
Distribution of disks on the pegs during the game must be assigned as sequence  D (element # i of the sequence is equal to the number of peg where the disk # i is placed on). For instance, game status after the third move is apparently determined by sequence  D=(3, 3, 1) (the first and the second disks are set on the third peg and the third disk is on the peg #1).
Example. Let's assume that 3 disks are set on the peg #1. Then the movement of the disks can be depicted in the following table (disks are numbered in ascending order of diameters):
Point of movePeg #1 disksPeg #2 disksPeg #3 diskssequence D
01, 2, 3--1, 1, 1
12, 31-2, 1, 1
23122, 3, 1
33-1, 23, 3, 1
4-31, 23, 3, 2
51321, 3, 2
612, 3-1, 2, 2
7-1, 2, 3-2, 2, 2

Problem

Your aim is either to determine (using arbitrary sequence  D) the number of moves from the beginning of the game to the given position on condition of performing the optimal algorithm; or to print "−1" in the case of incorrect sequence declaration (i.e. the given position cannot be achieved performing the optimal algorithm).
Reference notes. Optimal algorithm can be specified with the following recursive procedure.
procedure Hanoi(N:integer; From, To_, Temp : integer);
 Begin
  if N>0 then
  begin
     Hanoi(N-1, From, Temp, To_);
     writeln (N, From, To_);
     Hanoi(N-1, Temp, To_, From)
  end
End;
For example, to move 5 disks it's enough to call Hanoi(5,1,2,3)
Admonition. It is obvious that during the game process simultaneous setting of disks on all the pegs (#1, #2, #3) is never repeated, thus the answer will always be unequivocal.

Input

The first line of input contains integer  N (1 ≤  N ≤ 31). The other  N successive lines contain integers  D 1D 2, …,  DN.  1 ≤  D 1D 2, …,  DN ≤ 3 .

Output

Output should contain either the number of moves, or −1.

Sample

input output
3
3
3
1
3

题目中已经把汉诺塔的递归形式给出来了,然后就是可以利用这个模板做了。不过首先还是要理解了这个递归。
话说这是学递归的第一个例子。。。为毛我当时都没学呢。。。现在还不清楚。
其实大概理解还是很简单的,就是每次把n何其余的(n-1)看成两部分,每次先把(n-1)部分搬到3,然后n搬到2,然后换个角度,把3当做1来看,又是将(n-1)搬到2。所以f(n)=2*f(n-1)+1;
有公式f(n)=2^n-1;

//汉诺塔问题,主要是D序列 ,还要判断是否可以正确搬运 。。。 
//递归,假设目前状态有n个盘子: 1.当第n个盘子位于第1根柱子上,此时正在把n-1个盘子从1移到3。
//此时去掉第n个盘子,将第2、3根柱子交换,到达这一状态的步数等于到达原状态的步数 
//2.当第n个盘子位于第2根柱子上,此时正在把n-1个盘子从3移动到2。此时去掉第n个盘子,
//将第3、1根柱子交换,到达这一状态的步数+f[n-1]+1等于原步数 3.当第n个盘子位于第3根柱子上,此时必然无解,程序结束。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int d[40];
int res=0;
int flag;
void Hanoi(int n,int from,int tmp,int to)
{
	if(n==0 || !flag)return ;
	if(d[n]==from)
	{
		Hanoi(n-1,from,to,tmp);
	}
    else if(d[n]==to)
    {
    	res+=(1<<(n-1));
    	Hanoi(n-1,tmp,from,to);
    }
    else 
    {
    	flag=0;
    	res=-1;
    }
}
int main()
{
	int n,i,j;
	cin>>n;
	res=0;
	flag=1;
	for(i=1;i<=n;i++)cin>>d[i];
	Hanoi(n,1,3,2);
	cout<<res<<endl;

} 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值