You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 512 * 3 + 10;
char a[N][N];//疑问第一维为什么也要开N这么大按理说开N/2就够了
PII b[N][N];
int width;
//放过位置0后面是10个数字
//此数组的含义穷举出level=1234... 10时(从下往上),子树开始的位置。
const int col[11] = {0, 1, 3, 6, 12, 24, 48, 96, 192, 384, 768};
/**
* 功能:自顶向下画二叉树
* @param r 从哪一行开始
* @param c 从哪一列开始
* @param depth 深度
*/
void dfs(int r, int c, int depth) {
//此位置放上o
a[r][c] = 'o';
//如果到了叶子结点,递归结束
if (depth == 1) return;//这个depth是用来控制递归终止的判断是不是到了叶子
//树枝的个数,从当前结点到下一层结点间树枝的个数是多少,可以转化为求相邻结点的列差值
int cnt = col[depth] - col[depth - 1] - 1;
//下一步的左儿子,右儿子的位置
int lSonRow = r + 1, lSonCol = c - 1, rSonRow = r + 1, rSonCol = c + 1;
//执行几次,画出树干
for (int i = 1; i <= cnt; i++) {
a[lSonRow++][lSonCol--] = '/'; //在循环中动态修改左右儿子的位置坐标,继续填充
a[rSonRow++][rSonCol++] = '\\';
}
//递归填充左子树
dfs(lSonRow, lSonCol, depth - 1);
//递归填充右子树
dfs(rSonRow, rSonCol, depth - 1);
}
/**
* 功能:输出二维数组
*/
void print() {
//width为最长有效数据范围
for (int i = 1; i <= width; i++) {
for (int j = 1; j <= width; j++)
cout << a[i][j];
cout << endl;
}
}
/**
* 递归删除结点
* @param r 行
* @param c 列
*/
void delNode(int r, int c) {
a[r][c] = ' ';
if (a[r - 1][c - 1] == '\\') delNode(r - 1, c - 1);//向左上进行探索删除,向上不能删除o
else if (a[r - 1][c + 1] == '/') delNode(r - 1, c + 1);//向右上进行探索删除,向上不能删除o
//上面的可以使用else,因为一个位置只能向上有一条路径,不能既有左上,又有右上
//向下就很暴力了,不管是/ \ o全部干掉
if (a[r + 1][c - 1] == '/' || a[r + 1][c - 1] == 'o') delNode(r + 1, c - 1);
if (a[r + 1][c + 1] == '\\' || a[r + 1][c + 1] == 'o') delNode(r + 1, c + 1);
}
//生成每一行每一列每一个o的具体位置
//因为题目给的数据是第几行第几列的相对位置,需要转换为在数组中的绝对位置
void fillReleation() {
int row = 1;
for (int i = 1; i <= width; i++) {
int cnt = 0;
bool found = false;
for (int j = 1; j <= width; j++) {
if (a[i][j] == 'o') {//本行中找到o, cnt记录个数
cnt++;
found = true; //标识为找到本行找到后row++,找不到,不用++
b[row][cnt] = {i, j};
}
}
if (found) row++;
}
}
int main() {
int m; //绘制的二叉树层数
int delCnt; //要删除结点的个数
cin >> m >> delCnt;
//行和列都设置为空格
memset(a, ' ', sizeof a);
//给定m情况下的底层宽度
width = pow(2, m - 1) * 3;
//填充
dfs(1, col[m], m);
//生成具体位置对应关系表
fillReleation();
//删除结点
int x, y;
for (int i = 1; i <= delCnt; i++) {
cin >> x >> y;
delNode(b[x][y].first, b[x][y].second);
}
//打印
print();
return 0;
}