【蓝桥杯】 试题 算法提高 汉诺塔
问题描述
汉诺塔是一个古老的数学问题:
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
每次只能移动一个圆盘;
大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
每次只能移动一个圆盘;
大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
输入格式
一行,包含2个正整数,一个是N(N<=15),表示要移动的盘子数;一个是M,表示在最少移动d第M步
输出格式
共2行。
第一行输出格式为:#No: a->b,表示第M步骤具体移动方法,其中No表示第M步移动的盘子的编号(N个盘子从上到下依次编号为1到n),表示第M步是将No号盘子从a杆移动到b杆(a和b的取值均为{A、B、C})。
第2行输出一个整数,表示最少移动步数。
第一行输出格式为:#No: a->b,表示第M步骤具体移动方法,其中No表示第M步移动的盘子的编号(N个盘子从上到下依次编号为1到n),表示第M步是将No号盘子从a杆移动到b杆(a和b的取值均为{A、B、C})。
第2行输出一个整数,表示最少移动步数。
下面是大神的代码,搞了半天没看明白,贴上来以后再研究:
1 #include <stdio.h> 2 int main() 3 { 4 int N,M; 5 scanf("%d%d", &N, &M); 6 7 int n,r,s; 8 char c[3] = {'A','B','C'}; 9 n = 1; 10 while((M&1)==0) 11 { 12 n++; 13 M=M>>1; 14 } 15 M=M>>1; 16 r=(N+n)%2; 17 if (r) 18 { 19 s = M%3; 20 printf("#%d: %c->%c\n",n,c[s],c[(s+1)%3]); 21 } 22 else 23 { 24 s = 2-(M+2)%3; 25 printf("#%d: %c->%c\n",n,c[s],c[(s+2)%3]); 26 } 27 28 printf("%d\n",(1<<N)-1);//最小移动容步数 29 return 0; 30 }
自己写了一下,也能通过。关键代码参考了博客,里面也对汉诺塔及相关代码进行了详细讲解 https://blog.csdn.net/woshinannan741/article/details/52815187。
1 #include <stdio.h> 2 #include <cstring> 3 #include <string.h> 4 #include <iostream> 5 using namespace std; 6 int n,m; 7 int count = 0; 8 void hanoi(int n,char A,char B,char C) 9 { 10 11 if(n<=1) { 12 count++; 13 if(count==m) 14 printf("#1: %c->%c\n",A,C); 15 return ; 16 } 17 hanoi(n-1,A,C,B); 18 count++; 19 if(count==m) 20 printf("#%d: %c->%c\n",n,A,C); 21 hanoi(n-1,B,A,C); 22 } 23 int main(){ 24 //freopen("in.txt","r",stdin); 25 cin>>n>>m; 26 hanoi(n,'A','B','C') ; 27 cout<<(1<<n)-1<<endl; 28 return 0; 29 }