双色Hanoi塔图文详解

双色汉诺塔问题
C++实现
问题描述
设A、B、C是3个塔座。开始时,在塔座A上有一叠共n个圆盘,这些圆盘自下而上,由小到大地叠放在一起。各圆盘从小到大的编号为1,2,…,n,奇数号圆盘着红色,偶数号圆盘着蓝色。现要求将塔座A上的这一叠圆盘移动到塔座B上,并仍按同样顺序叠置。在移动圆盘时应遵守以下移动规则:
规则1:每次只能移动1个圆盘;
规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
规则3:任何时刻都不允许将同色圆盘叠放在一起;
规则4:在满足移动规则1~3的前提下,可将圆盘移至A、B、C中任一塔座上。

试设计一个算法,用最少的移动次数将塔座A上的n个圆盘移动到塔座B上,并仍按同样顺序叠置。

大体思路
先按照普通Hanoi塔问题的思路求解问题,再考虑此双色Hanoi问题与单色的区别,得出最终答案。

常规Hanoi塔解题思路
1、如果只有一个圆盘的话,那我们只需要把这唯一的一个圆盘从A移动到B上。

2、如果有n个圆盘,那我们可以把问题规模缩小,看看如果只有n-1个圆盘的话怎么移动,想n-1个圆盘怎么移动时,可以考虑n-2个怎么移动…这样一直缩小问题规模直到缩小到n=1。这个思路可以运用递归来解决,n=1就是递归的边界。

3、要将A塔座上的圆盘全部移动到B塔座上,中间必定要有一步是原本A塔座上面的n-1个圆盘全部移动到了C塔座上,然后就可以将A塔座上的最后一个圆盘n移动到B塔座上,然后就可以再把C上的n-1个圆盘移动到B上。然后再考虑那n-1个是怎么从A移动到C的。
在这里插入图片描述

普通Hanoi塔解题代码

#include<iostream>
using namespace std;
void Hannoi(int,char,char,char);
int main()
{
	int n;
	cin>>n;
	Hannoi(n,'A','B','C');
	return 0;
} 
void Move(int i,char M,char N)
{   //打印:把第i层塔从M位置移动到N位置
	cout<<i<<' '<<M<<' '<<N<<endl;  
}
void Hannoi(int n,char W1,char W2,char W3)
{
	if(n==1)
	{//如果只有一个圆盘,则直接从A移动到B
		Move(1,W1,W2);
		return;
	}
	n--;
	Hannoi(n,W1,W3,W2);//考虑A上面的n-1个圆盘是怎么从A移动到C的
	Move(n+1,W1,W2);//第n个从A到B(此处的n+1就是n,前面做了n--)
	Hannoi(n,W3,W2,W1);//考虑C上面的n-1个圆盘怎么从C移动到B上(此处的n就是n-1,前面做了n--)
}

运行结果
在这里插入图片描述

【普通与双色的联系】
我们不妨再多往下走一步,当把最后一个圆盘n移动到B塔座上之后,就要考虑如何把C塔座上的n-2个圆盘移动到A上,然后再把C上的圆盘n-1移动到B上,再把A上的n-2个移动到B上。从这个思路来看,我们每次递归时移动到一起的圆盘都是相邻的,也就是说是颜色不一样的,那么就不用担心普通汉诺塔的解法或造成颜色一样的圆盘叠在一起的情况。
在这里插入图片描述

我们在普通汉诺塔的代码基础上加上一个判断来验证我们的想法。

【双色Hanoi塔代码验证】

#include<iostream>
using namespace std;
void Hannoi(int,char,char,char,int*);
int num[3];//num[3]为ABC最上方的圆盘编号 
int main()
{
/*
我们为了验证前面的想法,加上一个记录数组,用来记录每挪动
一次后ABC三个塔座最上方的圆盘编号。如果塔座上没有圆盘,
则记录为0。
*/
	int n;
	cin>>n;
	num[0]=1;
	num[1]=0;
	num[2]=0;
	Hannoi(n,'A','B','C',num);
	return 0;
} 
void Move(int i,char M,char N)
{   //把第i层塔从M位置移动到N位置
	cout<<i<<' '<<M<<' '<<N<<' ';  
}
/*
1、在递归函数里加判断。添加的地方为每次调用Move函数之
后,即每输出一次挪动记录之后。
2、因为相同颜色的圆盘的序号都为奇数或者都为偶数,则两个
颜色相同的圆盘序号相加必为偶数,而两个颜色不同的圆盘序号
数相加必为奇数。
3、所以只需要判断圆盘本身的序号数加上要移动到的塔座最上
方的圆盘序号是否为偶数即可。如果为偶数,就说明此解法错
误,输出false。此判断还有一个特殊情况就是如果要移动到的塔
座上没有圆盘,就不用输出false,这是个特例。
*/
void Hannoi(int n,char A,char B,char C,int* num)
{
	if(n==1)
	{
		Move(1,A,B);
		if((num[A-'A']+num[B-'A'])%2==0&&num[B-'A']!=0){
			cout<<"false"<<endl;
		}
		
		else{
			cout<<"true"<<endl;
		}
		
		num[A-'A']=0;
		num[B-'A']=1;
		return;
	}
	n--;
	Hannoi(n,A,C,B,num);
	Move(n+1,A,B);
	if((num[A-'A']+num[B-'A'])%2==0&&num[B-'A']!=0){
		cout<<"false"<<endl;
	}
	else{
		cout<<"true"<<endl;
	}
	num[A-'A']=0;
	num[B-'A']=n+1;
	Hannoi(n,C,B,A,num);
}

【双色Hanoi塔验证代码运行结果】
在这里插入图片描述
在这里插入图片描述
分别用奇数个圆盘和偶数个圆盘来验证之前的想法,发现每一步都是正确的,没有出现相同颜色叠放的状态,则本双色Hanoi塔问题可以用普通Hanoi塔的解题思路来解决。

  • 17
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
双色Hanoi问题是指有两堆不同颜色的盘子,从一侧开始按照规则放置,现在需要将这两堆盘子按照规则全部移到另一侧。这个问题可以使用递归算法来解决。 具体思路如下: 1. 将第一堆盘子的上面 n-1 个盘子移动到第三个柱子上(空柱子); 2. 将第一个柱子上的最后一个盘子移动到第二个柱子上; 3. 将第三个柱子上的 n-1 个盘子移动到第二个柱子上。 其中第一步和第三步可以看作是同一个问题,因此可以使用递归来解决。具体实现时,可以将这个问题看作是将 n 个盘子从第一个柱子移动到第二个柱子,其中第三个柱子作为辅助柱子。因此,递归函数可以定义为: ```python def move(n, source, dest, aux): if n == 1: print("Move disk", n, "from", source, "to", dest) else: move(n-1, source, aux, dest) print("Move disk", n, "from", source, "to", dest) move(n-1, aux, dest, source) ``` 在这个递归函数中,参数 n 表示要移动的盘子数,source、dest、aux 表示三个柱子的编号。当 n=1 时,直接将盘子从 source 移动到 dest 即可,如果 n>1,则需要先将上面的 n-1 个盘子移动到辅助柱子上,再将最后一个盘子从 source 移动到 dest,最后再将辅助柱子上的 n-1 个盘子移动到 dest 上。 使用这个递归函数可以解决双色Hanoi问题。不过需要注意的是,对于双色Hanoi问题,需要将两堆盘子分别看作两个独立的问题来处理。在递归的过程中,需要使用不同的辅助柱子来保证两个问题之间不会相互干扰。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值