A Different Task(新汉诺塔问题)

本文探讨了一种灵活版的汉诺塔问题,不同于传统版本,该问题允许圆盘最初放置于任意柱子上,并提供了寻找最小移动步骤的算法实现。通过递归思想解决了从一种配置转换到另一种配置所需的最少移动次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

\epsfbox{p10795a.eps}

The (Three peg) Tower of Hanoi problem is a popularone in computer science. Briefly the problem isto transfer all the disks frompeg-A to peg-C using peg-B as intermediate one in such away that at no stage a larger disk is above a smaller disk. Normally, we wantthe minimum number of moves required for this task. The problem is used as anideal example for learning recursion. It is so well studied that one can findthe sequence of moves for smaller number of disks such as 3 or 4.A trivial computer program can find the case of large number of disks also.


Here we have made your task little bit difficult bymaking the problem more flexible. Here the disks can be in any peg initially.

\epsfbox{p10795b.eps}

If more than one disk is in a certain peg, then they will be in a valid arrangement (larger disk will not be on smaller ones). We will give you two such arrangements of disks. You willhave to find out the minimum number of moves, which will transform the firstarrangement into the second one. Of course you always have to maintain theconstraint that smaller disks must be upon the larger ones.

Input

Theinput file contains at most 100 test cases. Each test case starts with apositive integerN (1$ \le$N$ \le$60), which means thenumber of disks. You will be given the arrangements in next two lines. Eacharrangement will be represented byN integers, which are1, 2or 3. If the i-th (1$ \le$i$ \le$N)integer is 1, you should consider that i-th disk is onPeg-A. Input is terminated byN = 0. This case should not beprocessed.

Output

Outputof each test case should consist of a line starting with `Case #: ' where # is the test case number. It should be followed by the minimum numberof moves as specified in the problem statement.

Sample Input

3
1 1 1
2 2 2
3
1 2 3
3 2 1
4
1 1 1 1
1 1 1 1
0

Sample Output

Case 1: 7
Case 2: 3
Case 3: 0

参考了大刘的思想:
    假设要将第k个盘子移动从柱子1移动到柱子2,比编号k大的盘子不用理它,把他们当作空气;比编号k小的盘子既不能放在柱子1上也不能放在柱子2上,因此只能放在柱子3上。换句话说,这时柱子1只有盘子k,柱子2为空,柱子3从上到下一次为盘子1,2,3....,k-1。我们把这个居面叫做参考局面。
    由于盘子的移动是可逆的,根据对称性,我们只需要求出初始局面和目标局面移动成参考局面的步数之和,然后加1(移动盘子k)。设有函数fun(P,i,target),表示已知各个盘子的初始柱子编号数组为p,把p[i]移到target所需要的步数。则答案为:fun(start,k-1,6-start[k]-end[k])+fun(end,k-1,6-start[k]-end[k])。我们把柱子编号为1,2,3所以除了x,y之外的柱子为6 - x - y。
    当P[i] = target的时候,fun(p,i,target)=fun(p,i-1,target)+1。不相等时,fun(p,i,target)=fun(p,i-1,6-p[i]-target) + 2 ^(i-1)。
代码如下:
#include <cstdio>
__int64 fun(int *p,int i,int target)
{
	if (!i)
	{
		return 0;
	}
	if (p[i] == target)
	{
		return fun(p,i - 1,target);
	}
	return fun(p,i - 1,6 - p[i] - target) + (1L << (i - 1));
}
int n,start[60],end[60];
int main()
{
	int count = 0;
	while (scanf("%d",&n) == 1 && n)
	{
		for (int i = 1; i <= n; i++)
		{
			scanf("%d",&start[i]);
		}
		for (int j = 1; j <= n; j++)
		{
			scanf("%d",&end[j]);
		}
		int k = n;
		while (k >= 1 && start[k] == end[k])//最大编号不需要移动
		{
			k--;
		}
		__int64 tag = 0;
		if (k >= 1)
		{
			int target = 6 - start[k] - end[k];
			tag = fun(start,k - 1,target) + fun(end,k - 1,target) + 1;
		}
		printf("Case %d: %lld\n",++count,tag);
	}
	return 0;
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值