【9107】Hanoi双塔问题(NOIP2007)

Time Limit: 10 second
Memory Limit: 2 MB

问题描述
给定A,B,C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的。现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求: 
(1)每次只能移动一个圆盘; 
(2) A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。

Input

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

Output

输出仅一行,包含一个正整数,为完成上述任务所需的最少移动次数An。(最后用换行结束)

Sample Input

1

Sample Output

2

Sample Input2

2

Sample Output2

6

【题解】

先不考虑有相同圆盘的情况。

即n个不同的圆盘。

则需要把n-1个圆盘从a->b,然后把a上剩余的一个圆盘从a->c。然后把b上的n-1个圆盘从b->c。

这里的两步:把n-1个圆盘从a->c,和n-1个圆盘从b->c.所需要的步骤数。实际上就是把n-1个圆盘从a移动到c的步骤数*2,因为是等价的。从a->b和从b->c移动的圆盘个数都是一样的,这样。

然后还要多一步就是把a上的一个圆盘放到c。

所以得到递推式。(没有相同的圆盘。然后是n个不是2*n个的递推式)

An表示把n个圆盘从a到c的步骤数。

An=A(n-1)*2+1;

然后玩一下数学游戏。

An=A(n-1)*2+2-1;

An+1=A(n-1)*2+2;

An+1=2(A(n-1)+1)

令Bn = (An+1);

则Bn是一个等比数列。

A1只有把1个圆盘从a移到c,步骤为1

B1=A1+1 = 2;

所以Bn=2^n

然后An=2^n-1;

现在考虑有重复圆盘的情况。

其实只要乘上2就可以了。。

比如n==1.

A上有两个相同的圆盘。那就全都拿到C就好了。

只不过要多移动一次了而已。

然后每种圆盘都要多移动一次

设Dn为2*n个圆盘(n种)要从a移动到c的步骤数。

Dn=2*An=2^(n+1)-2;

然后n可能很大。要用高精度。

写一下高精度乘法即可。

【代码】

//2^(n+1)-2;
#include <cstdio>

int n, a[1000] = { 0 };//a数组用来存高精度的各个位上的数字。

void input_data()
{
	scanf("%d", &n);
}

void get_ans()
{
	a[0] = 1;
	a[1] = 1;//2^0 == 1;
	for (int i = 1; i <= n + 1; i++) //然后乘上n+1个2.
	{
		int x = 0;
		for (int j = 1; j <= a[0]; j++)//把每一位都乘上2.
		{
			a[j] = a[j] * 2 + x; //边乘边进位。
			x = a[j] / 10;
			a[j] = a[j] % 10;
		}
		while (x > 0) //可能要扩展位数。
		{
			a[0]++; 
			a[a[0]] = x % 10;
			x = x / 10;
		}
	}
	a[1] -= 2;//直接减去2就好。不会出现要退位的情况。
	//因为2的x次方除了2的0次方之外。其他的个位数字上的数字都大于等于2.这样。
}

void output_ans()
{
	for (int i = a[0]; i >= 1; i--) //倒序输出所有位上的数字。
		printf("%d", a[i]);
}

int main()
{
	input_data();
	get_ans();
	output_ans();
	return 0;
}


posted @ 2017-10-06 19:23  AWCXV  阅读(163)  评论(0编辑  收藏  举报