题目链接:
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;
}