題目描述
用 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;
}
}