标签:
题目详情:传送门
我都要做郁闷了,逻辑一直没错,但是最后一组答案就是过不了。看了几个小时,终于发现问题所在了。我把数组初始化 memset() 函数,放在了自定义函数 Input 中,使用形参的sizeof()作为地址的长度,结果数组没有初始化成功,导致悲剧的诞生。之后我把 memset() 中的地址长度改回数组长度问题终于解决了。刚做这一题时我把它当成栈混洗了,结果一直没琢磨明白。之后在网上一查,恍然大悟。霎时间,感觉好难过,为什么自己就没想到。下面我们来分析一下本题的思路吧。
分析:
这一题考查的递归的使用,又是一个以汉诺塔为载体的题目。用到递归那就要回归到这个问题的本质:既然要最优解,那么怎么样的才是最优解?如果你能想到这里,那么你就很接近成功了。其实要得到最优解的步骤其实只有三个:①先将第n个圆盘上的 n-1 个圆盘从 柱A 移动到 柱B ②将第n个圆盘从 柱A 移动到 柱C ③然后将之前的n-1个圆盘,再移到 柱C。通过这三个步骤,就可以以最优解的方式完成从 柱A 到 柱C 的移动。由此可见,要把n个圆盘从 柱A(借助柱B)移动到 柱C,那么一定要把第n个圆盘移动到 柱C,换而言之,就是 第n个圆盘一定是在 柱A 和 柱C 之间的,如果不在那么肯定不是最优解。以此类推,要将n-1个圆盘从柱A(借助柱C)移动到 柱B,那么第 n - 1个圆盘 一定在 柱A 和 柱B 之间。到了这里问题就基本解决了,剩下的就只有用你的双手在键盘上飞舞就可以了。
本题代码如下:
#include <stdio.h> #include <string.h> #define MAXN 65 + 10 void Input(int *in_arr){ int i; memset(in_arr,0,MAXN*sizeof(int) ); scanf("%d",&in_arr[0]); for(i = 1; i <= in_arr[0]; i++) scanf("%d",&in_arr[i]); } bool hanoi(int n,int *a,int *b,int *c){ if(!n) //如果n等于0,那么当然就是true return true; if( n == a[1] ) //如果第n个圆盘在柱A上,那么就将 柱A 上的n-1个圆盘(除第n个圆盘以外的圆盘)通过 柱C 移动到 柱B 上 return hanoi(n-1,++a,c,b); else if(n == c[1]) //如果第n个圆盘在柱C上,那么就将 柱B上的n-1个圆盘,通过柱A移动到柱B上 return hanoi(n-1,b,a,++c); return false; //否则返回false } int main(){ int T,n; int A[MAXN],B[MAXN],C[MAXN]; scanf("%d",&T); while(T--){ scanf("%d",&n); Input(A); Input(B); Input(C); if(hanoi(n,A,B,C)) printf("true\n"); else printf("false\n"); } return 0; }
(如有错误,欢迎指正,如有转载请注明出处)
标签:
原文地址:http://blog.csdn.net/luomingjun12315/article/details/44986379