解题思路:
发现数据范围并不太大,可直接使用char类型的二维数组来存储各个字符。我们为了操作方便使用int类型数组,0代表 . ,1代表 - , 2代表 | ,3代表 +,其他代表对应的填充字符的anscii码。先对二维数组g全部初始化为0,然后根据标志位不同分别进行连线和填充字符的操作。当连线时,区分横坐标还是纵坐标不变,还要区分两个不同坐标谁大谁小。如果已有连线和当前预连线不同或已有连线为+号则填充+号,否则一律填充当前预连线。然后进行填充字符操作时,采用dfs搜索,当坐标超界或者到达已有连线或已经填充过该字符时结束递归(return),否则填充该字符并循环递归上下左右四个坐标。然后按照顺序进行输出,注意每行末尾输出换行符。
注意事项:
1、很重要的一个注意点在于题目中所给坐标和我们的二维数组g的坐标的相互转换。这一点在涉及到二维数组的问题时尤其需要注意。题目中的任意一点(x,y)在g中的坐标应该是(n-1-y,x),注意当使用的就是g中坐标时需要进行正确的坐标转换。由于dfs的参数已经转换过一次了故dfs函数中无需再进行二次转换。题目中坐标(x,y)的范围为x<m,y<n,g中坐标(x,y)的范围为x<n,y<m。
2、在输出时,只需要在g数组中从上到最小,从左至右一次输出即可满足题目要求,因而不需要再进行坐标转换。
总结:
尽管在csp的第三题,但难度并不大,主要需要掌握好dfs遍历的思想,注意递归结束条件的判断以及二维数组坐标和题目中所给实际坐标的转换问题。
参考代码:
#include <bits/stdc++.h>
using namespace std;
int m,n;
int g[105][105];
// 0 .
// 1 -
// 2 |
// 3 +
// char
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y,char c){
if(g[x][y]!=1&&g[x][y]!=2&&g[x][y]!=3&&g[x][y]!=c&&x>=0&&x<n&&y>=0&&y<m){
g[x][y]=c;
}
else return;
for (int i=0; i<4; i++) {
dfs(x+dx[i], y+dy[i], c);
}
}
int main(int argc, const char * argv[]) {
memset(g,0,sizeof(g));
int q,flag,a,b,c,d;
char ch;
cin>>m>>n>>q;
while (q--) {
cin>>flag;
if(flag==0){
cin>>a>>b>>c>>d;
if(a==c){
if(b>d)
for (int i=b; i>=d; i--) {
if(g[n-1-i][a]==1||g[n-1-i][a]==3)g[n-1-i][a]=3;
else g[n-1-i][a]=2;
}
else//b<d
for (int i=b; i<=d; i++) {
if(g[n-1-i][a]==1||g[n-1-i][a]==3)g[n-1-i][a]=3;
else g[n-1-i][a]=2;
}
}
else//b==d
{
if(a>c)
for (int i=a; i>=c; i--) {
if(g[n-1-b][i]==2||g[n-1-b][i]==3)g[n-1-b][i]=3;
else g[n-1-b][i]=1;
}
else//a<c
for (int i=a; i<=c; i++) {
if(g[n-1-b][i]==2||g[n-1-b][i]==3)g[n-1-b][i]=3;
else g[n-1-b][i]=1;
}
}
}
else if(flag==1){
cin>>a>>b>>ch;
dfs(n-1-b, a, ch);
}
}
for (int i=0; i<n; i++){
for(int j=0;j<m;j++)
{
if(g[i][j]==0)cout<<'.';
else if(g[i][j]==1)cout<<'-';
else if(g[i][j]==2)cout<<'|';
else if(g[i][j]==3)cout<<'+';
else printf("%c",g[i][j]);
}
cout<<endl;
}
return 0;
}