|
|
#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=1,2,3,4,... ,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;
|
|
|
} |