题目链接:

https://ac.nowcoder.com/acm/problem/201605

题面:

Nancy喜欢做游戏! 汉诺塔是一个神奇的游戏,神奇在哪里呢? 给出3根柱子,最开始时n个盘子按照大小被置于最左的柱子。 如果盘子数为偶数,则需要将她们全部移动到最右侧的柱子上,否则将她们移动到中间的柱子上。 那么,Nancy该怎样移动呢?请你输出汉诺塔游戏的过程叭!

输入描述:
共一行:一个整数n,表示最开始n个盘子(编号为1到n)的放置方法。

数据满足:2≤n≤11。
输出描述:
共2^n组:每组n+2行,每行3×(2n+1)+4个字符,用.表示空白区域,用|表示柱子区域,用*表示盘子。组与组之间请输出3×(2n+1)+4个-。
具体输出方式请参看样例进行理解。

样例:
input:
2

output:
...................
...|.....|.....|...
..***....|.....|...
.*****...|.....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
.*****..***....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
...|....***..*****.
-------------------
...................
...|.....|.....|...
...|.....|....***..
...|.....|...*****.

分析+代码:

本题是模拟题,模拟汉诺塔移动过程,我使用 STL 存储,方便快捷。

#include<iostream>
#include<stack>
#include<vector>
#include<map>
#include<algorithm>
#include<math.h>
#include<windows.h>

using namespace std;

int len = 0;
int flag = 0; // 用来控制输出的分隔符

vector<int> input_plate;


map<char, stack<int>> mp_st;

/*

n = 1
13 个 .

  3   7   11
.............
..|...|...|..
.***..|...|..
-------------
.............
..|...|...|..
......|..***.
-------------


n = 2
19 个 .

   4     10    16
...................
...|.....|.....|...
..***....|.....|...
.*****...|.....|...
-------------------


n = 3
25 个 .

    5       13      21
.........................
....|.......|.......|....
...***......|.......|....
..*****.....|.......|....
.*******....|.......|....
-------------------------


最小盘子为3个*,之后每次加2个*,
n阶最大盘子宽度为(2×(n-1)+3) = (2×(n+1)) = (2n+2)
有三根柱子,因此3 × (2n + 1) = (3×(2n+2))

3 × (2n + 1) + 4 = 3×(2n+2) + 1

注意柱子插法


*/

void move(int n, char x, char y) {
	
	//	cout << endl << x << " -> " << y << endl;
	
	// 本次手工移动 —— 从 柱x 移动到 柱y
	mp_st[y].push(mp_st[x].top());
	mp_st[x].pop();	
	
	
	int width = 3 * (2 * len + 1) + 4;
	int plate = 3 + 2 * (len - 1);
	
	int half_plate = plate/2;
	
	if (flag > 0 && flag <= pow(2, len) - 1) {
		for (int i = 0; i < 3 * (2 * len + 1) + 4; i++) {
			cout << "-";
		}
		cout << endl;
	}
	flag++;
	
	
	
	for (int i = 0; i < width; i++) {
		cout << ".";
	}	
	cout << endl;
	
	
	// 最上层空柱子
	cout << ".";
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < half_plate; j++) {
			cout << ".";
		}	
		cout << "|";
		for (int j = 0; j < half_plate; j++) {
			cout << ".";
		}
		cout << ".";	
	}
	cout << endl;
	
	
	map<char, stack<int>> tmp_st = mp_st;
	
	for (int floor = len; floor > 0; floor--) {  // 剩余层数
		cout << ".";
		// 剩下 3柱 * ( (2n+1)字符每柱  + 1 占位符.结尾)
		
		// 按顺序查询 ABC 三柱
		
		// A柱
		if (tmp_st['A'].size() == floor) {
			for (int j = 0; j < (plate - tmp_st['A'].top())/2; j++) {
				cout << ".";
			}
			for (int j = 0; j < tmp_st['A'].top(); j++) {
				cout << "*";
			}
			for (int j = 0; j < (plate - tmp_st['A'].top())/2; j++) {
				cout << ".";
			}
			cout << ".";
			tmp_st['A'].pop();
		}
		else {
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}	
			cout << "|";
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}
			cout << ".";
		}
		
		// B柱
		if (tmp_st['B'].size() == floor) {
			for (int j = 0; j < (plate - tmp_st['B'].top())/2; j++) {
				cout << ".";
			}
			for (int j = 0; j < tmp_st['B'].top(); j++) {
				cout << "*";
			}
			for (int j = 0; j < (plate - tmp_st['B'].top())/2; j++) {
				cout << ".";
			}
			cout << ".";
			tmp_st['B'].pop();
		}
		else {
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}	
			cout << "|";
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}
			cout << ".";
		}
		
		// C柱 ,记得换行
		if (tmp_st['C'].size() == floor) {
			for (int j = 0; j < (plate - tmp_st['C'].top())/2; j++) {
				cout << ".";
			}
			for (int j = 0; j < tmp_st['C'].top(); j++) {
				cout << "*";
			}
			for (int j = 0; j < (plate - tmp_st['C'].top())/2; j++) {
				cout << ".";
			}
			cout << "." << endl;
			tmp_st['C'].pop();
		}
		else {
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}	
			cout << "|";
			for (int j = 0; j < half_plate; j++) {
				cout << ".";
			}
			cout << "." << endl;
		}
		
	}
	//	Sleep(800);
	
}

void hanoi(int n, char a, char b, char c) {
	
	if (n == 0) {
		return ;
	}
	
	hanoi(n-1, a, c, b);
	
	move(n-1, a, c);
	
	hanoi(n-1, b, a, c);
	
	
}




int main () {
	
	
	cin >> len;
	
	for (int i = 1; i <= len; i++) {
		input_plate.push_back(2 * (i-1) + 3);	
	}
	
	
	// 三根柱子初始化
	mp_st['A'];
	mp_st['B'];
	mp_st['C'];
	
	reverse(input_plate.begin(), input_plate.end());
	for (auto p : input_plate) {
		mp_st['A'].push(p);
	}
	
	// 打印初始化
	move(len, 'A', 'A');
	
	if (len % 2  == 0) {
		hanoi(len, 'A', 'B', 'C');
	}
	else {
		hanoi(len, 'A', 'C', 'B');
	}
	
	return 0;
	
}