题目描述
用 ASCII 字符来画图是一件有趣的事情,并形成了一门被称为 ASCII Art 的艺术。例如,下图是用 ASCII 字符画出来的 CSPRO 字
样。
本题要求编程实现一个用 ASCII 字符来画图的程序,支持以下两种操作:
Ÿ 画线:给出两个端点的坐标,画一条连接这两个端点的线段。简便起见题目保证要画的每条线段都是水平或者竖直的。水平线段用字符 - 来画,竖直线段用字符 | 来画。如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。
Ÿ 填充:给出填充的起始位置坐标和需要填充的字符,从起始位置开始,用该字符填充相邻位置,直到遇到画布边缘或已经画好的线段。注意这里的相邻位置只需要考虑上下左右 4 个方向,如下图所示,字符 @ 只和 4 个字符 * 相邻。
输入
输出
输出有n行,每行m个字符,表示依次执行这q个操作后得到的画图结果。 |
样例输入
16 13 9
0 3 1 12 1
0 12 1 12 3
0 12 3 6 3
0 6 3 6 9
0 6 9 12 9
0 12 9 12 11
0 12 11 3 11
0 3 11 3 1
1 4 2 C
样例输出
................
...+--------+...
...|CCCCCCCC|...
...|CC+-----+...
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC+-----+...
...|CCCCCCCC|...
...+--------+...
................
思路
综述
这个题用到了两点:
1)图的搜索遍历;
2)坐标之间的转换
地图问题
因为每个点对于一个字符,所以可以初始化一个较大的二维char数组,初始化为’.’;
坐标转换问题
题目给出的(x,y)转换为字符数组中的(new_x,new_y);
假设图的高度为n,则:
new_x = n-y-1;
new_y = x;
图的遍历
既可以用bfs也可以dfs,比较基础
注意一点:
如下所示,在搜索的过程中注意,到达过,可用如下标记一下,即:到达的点不能是和本字符一样的。
if (ch[x][y] == c)return;
过程
Step1:输入
在输入的时候,进行坐标转换
n为地图的高度
int x1, y1, x2, y2;
int newx1, newy1, newx2, newy2;
cin >> x1 >> y1 >> x2 >> y2;
newx1 = n - y1;
newy1 = x1;
newx2 = n - y2;
newy2 = x2;
Step2:dfs过程
判断是否能够进行
条件1:已经到达过了(记忆化搜索)
if (ch[x][y] == c)return;
条件2:触碰到边界
if (x < 0 || y < 0)return;
if (x > n-1 || y > m-1)return;
条件3:触碰到画的线了
if((ch[x][y] == '|' || ch[x][y] == '-' || ch[x][y] == '+'))return;
满足上述条件之一,即不能继续进行;当return;
记录
if (ch[x][y] != '|' && ch[x][y] != '-' && ch[x][y] != '+')
ch[x][y] = c;
继续往下进行
只有四个方向:上、下、左、右;
dfs(x + 1, y, c);
dfs(x - 1, y, c);
dfs(x, y + 1, c);
dfs(x, y - 1, c);
Step3:画线问题
只需要一个循环即可:
假定所画的是竖线:
碰到相反方向的线要注意画为‘+’
碰到‘+’或者‘|’都continue
for (int i = x1; i <= x2; i++) {
//cout << i;
if (ch[i][y1] == '+')continue;//碰到‘+’
else if (ch[i][y1] == '-') ch[i][y1] = '+';
else if (ch[i][y1] == '|') continue;//碰到'|'
else ch[i][y1] = '|';
}
横线上同;
总结
1、图的搜索问题,大多数情况下需要记忆化的搜索,如本题,刚开始没加上下面的语句,导致陷入一种死循环的状态。
if (ch[x][y] == c)return;
2、坐标的转换问题
可能会遇到题目给出的坐标和数组内的坐标不同的情况,就需要进行如下的转换:
代码
#include <iostream>
#include <algorithm>
using namespace std;
int m, n, q;
char ch[150][150];
void dfs(int x,int y, char c) {
//剪枝
if (ch[x][y] == c)return;
if (x < 0 || y < 0)return;
if (x > n-1 || y > m-1)return;
if (ch[x][y] != '|' && ch[x][y] != '-' && ch[x][y] != '+')
ch[x][y] = c;
if((ch[x][y] == '|' || ch[x][y] == '-' || ch[x][y] == '+'))return;
//继续搜索
dfs(x + 1, y, c);
dfs(x - 1, y, c);
dfs(x, y + 1, c);
dfs(x, y - 1, c);
}
void line(int x1,int y1,int x2,int y2) {
if (y1 == y2) {
//画竖线问题
if (x1 > x2)swap(x1, x2);
for (int i = x1; i <= x2; i++) {
//cout << i;
if (ch[i][y1] == '+')continue;
else if (ch[i][y1] == '-') ch[i][y1] = '+';
else if (ch[i][y1] == '|') continue;
else ch[i][y1] = '|';
}
}
//画横线问题
else if (x1 == x2) {
if (y1 > y2)swap(y1, y2);
for (int i = y1; i <= y2; i++) {
if (ch[x1][i] == '+')continue;
else if (ch[x1][i] == '-') continue;
else if (ch[x1][i] == '|')ch[x1][i] = '+';
else ch[x1][i] = '-';
}
}
}
int main() {
cin >> m >> n >> q;
int op;
//初始化地图
for (int i = 0; i < 150; i++)
for (int j = 0; j < 150; j++)
ch[i][j] = '.';
for (int i = 0; i < q; i++) {
cin >> op;
if (op == 0) {
int x1, y1, x2, y2;
int newx1, newy1, newx2, newy2;
cin >> x1 >> y1 >> x2 >> y2;
//坐标转换
newx1 = n - y1;
newy1 = x1;
newx2 = n - y2;
newy2 = x2;
line(newx1-1, newy1, newx2-1, newy2);
}
else if (op == 1) {
int x1, y1;
int newx1, newy1;
char x;
cin >> x1 >> y1;
cin >> x;
//坐标转换
newx1 = n - y1-1;
newy1 = x1;
dfs(newx1, newy1, x);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << ch[i][j];
}
cout << endl;
}
}