luogu1096 Hanoi双塔问题(NOIP2007普及组第4题)(高×低)

luogu1096  Hanoi双塔问题(NOIP2007普及组第4题)

时空限制    1000ms/128MB

题目描述

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

luogu1096 Hanoi双塔问题(NOIP2007普及组第4题)(高×低)_第1张图片

现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:

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

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

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

输入输出格式

输入格式:

输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。

输出格式:

输出文件hanoi.out仅一行,包含一个正整数, 为完成上述任务所需的最少移动次数An。

输入输出样例

输入样例#1:

【输入样例1】
1
【输入样例2】
2

输出样例#1:

【输出样例1】
2
【输出样例2】
6

说明

【限制】

对于50%的数据,1<=n<=25

对于100%的数据,1<=n<=200

【提示】

设法建立An与An-1的递推关系式。

 

分析

汉诺塔移动n个盘的次数是2^n -1次,比如移动一个盘1次,两个盘3次,三个盘7次......

那么汉诺双塔移动2n个盘的次数:看成移动n组盘(每组2个相同的)移动组数就是2^n -1次,每组每次移动2次

答案:2*(2^n -1)次   即 2^(n+1) -2

就是求高精度数  2^(n+1) -2

 

代码

法一:数组模拟

#include
#include
using namespace std;
const int N = 100;
int n,a[N];

void pow(int n,int a[]){
    fill(a,a+N,0);
    a[0]=a[1]=1;
    for (int i=1; i<=n; i++){
        for (int j=1; j<=a[0]; j++) a[j]*=2;
        for (int j=1; j<=a[0]; j++)
            a[j+1]+=a[j]/10,a[j]%=10;
        if (a[a[0]+1]) a[0]++;
    }
}

void output(int a[]){
    for (int i=a[0]; i>1; i--) cout<>n;
    pow(n+1,a);
    output(a);
    return 0;
}

法二:重载运算符

#include
#include
using namespace std;
const int N = 10005;
struct bigint{
	int s[N];
	bigint(){ fill(s,s+N,0); s[0]=1; }	//默认初始化全0
	bigint(int x){ *this=x; }			//int类型初始化
	bigint operator = (int x){			//重载int赋值运算
		fill(s,s+N,0);
		do {
			s[++s[0]] = x%10;
			x /= 10;
		} while (x);
		return *this;
	}
	bigint operator * (const int &b){	//重载* 高*低
		bigint c(*this);
		for (int i=1; i<=c.s[0]; i++) c.s[i]*=b;
		for (int i=1; i<=c.s[0]; i++)
			c.s[i+1]+=c.s[i]/10, c.s[i]%=10;
		while (c.s[c.s[0]+1]){
			c.s[0]++;
			c.s[c.s[0]+1] += c.s[c.s[0]]/10;
			c.s[c.s[0]] %= 10;
		}
		c.clear0();
		return c;
	}
	void clear0(){						//清掉高位0,保证数据至少1位
		while (s[s[0]]==0&&s[0]>1) s[0]--;
	}
	bigint operator *= (const int &b){ *this=*this*b; return *this; }	//重载*=
};

ostream& operator << (ostream &out,const bigint &x){//重载输出流
	for (int i=x.s[0]; i>=2; i--) out<>n;
	bigint f=1;							/*需重载 int赋值*/
	for (int i=1; i<=n+1; i++) f*=2;	/*需重载高*低 高*=低*/
	cout<

你可能感兴趣的:(高精度,NOIP普及组,递推)