hdu1997 汉诺塔VII(DFS递归调用)

题目详情:传送门

       我都要做郁闷了,逻辑一直没错,但是最后一组答案就是过不了。看了几个小时,终于发现问题所在了。我把数组初始化 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;
}

(如有错误,欢迎指正,如有转载请注明出处)

       


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值