4.28 洛谷 P1096 Hanoi 双塔问题

题目描述

给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为 n=3 的情形)。

4.28 洛谷 P1096 Hanoi 双塔问题_第1张图片
现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:

(1)每次只能移动一个圆盘;

(2)A、B、C三根细柱上的圆盘都要保持上小下大的顺序;

任务:设 An 为 2n 个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出 An 。

输入格式

一个正整数n,表示在A柱上放有2n个圆盘

输出格式

一个正整数, 为完成上述任务所需的最少移动次数An 。

输入输出样例

输入#1: 1 __ 输出#1: 2
输入#2: 2 __ 输出#2: 6

说明

  • 对于50%的数据,1 ≤ n ≤ 25
  • 对于100%的数据,1 ≤ n ≤ 200

思路

本题对于普通的汉诺塔的区别是圆盘是成双出现的,根据小的只能放在大的圆盘上面,我们其实可以把两个相同的圆盘看成一个,只要在每次移动操作的时候多移动一次即可。还有就是找出移动的递推规律。总结方法如下:

  • 由汉诺塔递推规律不难发现,圆盘移动次数和圆盘数的关系为:f(x) = 2*f(x-1) + move;
  • 根据思路得到每次move操作移动两个相同得圆盘,move = 2;
  • 当然,在记录次数的时候必须使用高精度加法和高精度乘法;

接下来就是实现了

#include 

using namespace std;

int n, len;
int count[201]={0};				//用来存次数的数组; 

void gjc()						//高精度乘法 
{
//	cout << "gjc\n";
	int t;
	for(int i=len; i>=1; i--)	//一定要从高位到底位这样产生进位的话,也不会影响后面的运算; 
	{
		t = count[i]*2;
		if (t >= 10) {
			count[i] = t%10;
			count[i+1] += t/10;
		}
		else count[i] = t;
	}
	if (count[len+1] > 0) len++;//判断最高位的进位 
}

void gjj()						//高精度加法 
{
//	cout << "gjj\n";
	int t;
	count[1] += 2;				//加2操作 
	for(int i=1; i<=len; i++)
	{
		if(count[i] >= 10) {
			count[i] %= 10;
			count[i+1] += 1;
		}
		else break;
	}
	if (count[len+1] > 0) len++;//判断最高位的进位 
}

int main()
{
	cin >> n;
	count[1] = 0;				 
	len = 1;					//初始化长度为1,初始次数是0; 
	for(int i=1; i<=n; i++)		 
	{
		gjc();					 
		gjj();					//先进行高精乘,再进行高精加; 
	}
	for(int i=len; i>=1; i--)	//从高到低输出每一位; 
		cout << count[i];
	return 0;
}

蒟蒻一只,欢迎指正

你可能感兴趣的:(LanQiao校内训练)