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:
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.
It is well known and rather easy to prove that the minimum number of moves needed to complete the puzzle withn disks is . 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 ; for even moves, make the only possible move not involving disk 1.
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, ], will be the number of the last move. The file will end at a line formed by two zeros.
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.
3 5 64 2 8 45 0 0
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
#include
#include
#include
#include
#include
#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>=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;
}