uva254 - Towers of Hanoi 递归

来源:互联网 发布:盗号软件万能钥匙 编辑:程序博客网 时间:2024/05/14 04:19

 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 istex2html_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 564 28 450 0

Sample Output

1 1 162 1 14 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 0x3f3f3f3fusing 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
原创粉丝点击