uva254 - Towers of Hanoi 递归

 Towers of Hanoi 

In 1883, Edouard Lucas invented, or perhaps reinvented, one of the most popular puzzles of all times - the Tower of Hanoi, as he called it - which is still used today in many computer science textbooks to demonstrate how to write a recursive algorithm or program. First of all, we will make a list of the rules of the puzzle:

  • There are three pegs: A, B and C.
  • There are n disks. The number n is constant while working the puzzle.
  • All disks are different in size.
  • The disks are initially stacked on peg A so that they increase in size from the top to the bottom.
  • The goal of the puzzle is to transfer the entire tower from the A peg to one of the others pegs.
  • One disk at a time can be moved from the top of a stack either to an empty peg or to a peg with a larger disk than itself on the top of its stack.

A good way to get a feeling for the puzzle is to write a program which will show a copy of the puzzle on the screen and let you simulate moving the disks around. The next step could be to write a program for solving the puzzle in a efficient way. You don't have to do neither, but only know the actual situation after a given number of moves by using a determinate algorithm.

The Algorithm

It is well known and rather easy to prove that the minimum number of moves needed to complete the puzzle withn disks is tex2html_wrap_inline44 . A simple algorithm which allows us to reach this optimum is as follows: for odd moves, take the smallest disk (number 1) from the peg where it lies to the next one in the circular sequence tex2html_wrap_inline46 ; for even moves, make the only possible move not involving disk 1.

Input

The input file will consist of a series of lines. Each line will contain two integersn, m: n, lying within the range [0,100], will denote the number of disks andm, belonging to [0, tex2html_wrap_inline44 ], will be the number of the last move. The file will end at a line formed by two zeros.

Output

The output will consist again of a series of lines, one for each line of the input. Each of them will be formed by three integers indicating the number of disks in the pegsA, B and C respectively, when using the algorithm described above.

Sample Input

3 5
64 2
8 45
0 0

Sample Output

1 1 1
62 1 1
4 2 2

  汉诺塔。。这个很是有点坑啊。。给你盘子的个数和移动的步数,问此时的盘子的状态。

  移动完成n个盘子的汉诺塔需要2^n-1步,可以想到2进制,n个1。假设把A的盘子移到C。那么先把n-1个盘子移到B,需要2^(n-1)-1步,再把A上最下面的盘子移到C,要一步。也就是通过2^(n-1)次移动就完成了最大的盘子到C,并且其他盘子都在B上。换成2进制就是最高位是1。现在就变成了n-1个盘子同样的问题,只是要从B移动到C,也就是A盘和B盘交换了。但是如果移动的步数少于2^(n-1),最下面的盘子就没有被移动,状态就成了要把n-1个盘子移动到B,此时把B盘和C盘交换。

  所以思路就是把步数换成2进制,递归做。从n-1位开始(最高位时盘子数是总数N个,每判断一位就能确定一个盘子的位置,所以每减少一位操作的盘子数减1,设为n),判断每一位是1还是0。如果是1,A的最底下的盘子就移动到C,把n-1个盘子移动到B,接着递归(A和B交换位置)。如果是0,A最底下的就不动,接着递归(B和C交换位置)。

  这道题第一坑的是还要写个大数除以2的除法来求出2进制(每步最后的余数存到数组里),第二坑是他不是要求最后完成是放到C上,而是第一步放B上,所以有偶数个盘子的时候最后是全放在C上,有奇数个盘子的时候是最后全在B上。


#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cctype>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int ans[5],b[130];
char str[130];
void binary(){
    int i,p=0,k=0,l,a[130];
    memset(b,0,sizeof(b));
    l=strlen(str);
    for(i=0;i<l;i++) a[i]=str[i]-'0';
    while(p<l){
        int mod=0;
        for(i=p;i<l;i++){
            a[i]=mod*10+a[i];
            mod=a[i]&1;
            a[i]>>=1;
        }
        b[k++]=mod;
        if(!a[p]) p++;
    }
}
void hanoi(int A,int B,int C,int k){
    if(k<=0) return;
    if(b[k-1]){
        ans[A]-=k;
        ans[B]+=k-1;
        ans[C]++;
        hanoi(B,A,C,k-1);
    }
    else hanoi(A,C,B,k-1);
}
int main(){
   // freopen("in.txt","r",stdin);
    int N;
    while(scanf("%d%s",&N,str),N||str[0]!='0'){
        binary();
        ans[0]=N;
        ans[1]=0;
        ans[2]=0;
        if(N%2) hanoi(0,2,1,N);
        else hanoi(0,1,2,N);
        printf("%d %d %d\n",ans[0],ans[1],ans[2]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值