牛客小白月赛21有趣的题目
1.B bits
题目描述
Nancy喜欢做游戏!
汉诺塔是一个神奇的游戏,神奇在哪里呢?
给出3根柱子,最开始时n个盘子按照大小被置于最左的柱子。
如果盘子数为偶数,则需要将她们全部移动到最右侧的柱子上,否则将她们移动到中间的柱子上。
那么,Nancy该怎样移动呢?请你输出汉诺塔游戏的过程叭!
输入描述:
共一行:一个整数n,表示最开始n个盘子(编号为1到n)的放置方法。
数据满足:2≤n≤11。
输出描述:
共2^n组:每组n+2行,每行3×(2n+1)+4个字符,用.表示空白区域,用|表示柱子区域,用*表示盘子。组与组之间请输出3×(2n+1)+4个-。
具体输出方式请参看样例进行理解。
示例1
输入
复制
2
输出
复制
...................
...|.....|.....|...
..***....|.....|...
.*****...|.....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
.*****..***....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
...|....***..*****.
-------------------
...................
...|.....|.....|...
...|.....|....***..
...|.....|...*****.
题目解释
使用的想法是用二进制来解决汉诺塔的相关问题。详细的解释可以参照B站视频。我们可以发现,假设一共是n个盘子,移动总次数为2n-1次,当n为奇数时,我们可以将盘子移至中间,n为偶数是,我们可以将盘子移至最右边。所以我们就得到了移动的总次数。
#include <cstdio>
#include <stack>
using namespace std;
char map[103][103];
int n;
int w[13];
stack<int> s[3],temp;
//s[3]用来模拟三根柱子,先进后出所以用栈
void input(){
scanf("%d",&n);
}
void output(int n){
int x = n + 2;
int y = 3 * (2 * n + 1) + 4;
//先全部置为.
for(int i = 0;i < x;i++){
for(int j = 0;j < y;j++){
map[i][j] = '.';
}
}
int now = n + 1;
//在中间添加柱子
for(int i = 0;i < 3;i++){
for(int j = 1;j < x;j++){
map[j][now] = '|';
while(s[i].size()){
temp.push(s[i].top());
s[i].pop();
}
//从最后一行开始输出盘子
int tot = n + 1;
while(temp.size()){
int x = temp.top();
for(int l = now - x;l <= now + x;l++){
map[tot][l] = '*';
}
tot--;
s[i].push(x);
temp.pop();
}
}
now += 2 * n + 1;
}
for(int i = 0;i < x;i++){
for(int j = 0;j < y;j++){
putchar(map[i][j]);
}
puts("");
}
}
//输出分割
void split(){
int y = 3 * (2 * n + 1) + 4;
for(int i = 0;i < y;i++){
printf("-");
}
puts("");
}
void work(){
for(int i = n;i >= 1;i--){
s[0].push(i);//首先所有盘子都在第一根柱子
w[i] = 0;//w数组用来指示每一个盘子所在的柱子
}
output(n);//第一次输出
int p = (1 << n) - 1;//移动的总次数
for(int i = 1;i <= p;i++){
split();
int num;
for