【CCF-CSP】201512-3 画图 C++


一、题目

在这里插入图片描述
在这里插入图片描述

原题目链接

二、解题

1.思路

一个简单的画图软件,用户可以输入两种类型的操作指令:

  1. 画线:给定两个点和颜色,将这两个点之间的空白处填充为颜色,并在可以相接的地方添加符号“-”或“|”,即可以将两个线段相连成“+”形状。
  2. 填充:给定一个点和颜色,将该点所在的连通块以指定颜色填充。

实现中, m m m n n n 分别代表画布的宽和高, g g g 数组存储画布上每个位置的字符(‘.’ 表示空白,‘-’ 表示横向线段,‘|’ 表示竖向线段,‘+’ 表示相交的线段)。 s t st st 数组用于记录填充操作时已经访问过的点。

在实现画线操作时,代码中定义了函数 changePoint,用于将坐标系转换为实际的坐标值。然后针对给定的两个点,分别计算需要绘制的线段的位置。如果两个点在同一行,则从左到右依次将相应的位置填为“-”或“+”;如果在同一列,则从上到下依次将相应位置填为“|”或“+”。

在实现填充操作时,首先通过调用 changePoint 函数将坐标系转换为实际坐标值,然后使用深度优先搜索(DFS)遍历与给定点连通的图形,并将遇到的每个点填充为指定颜色。

最后,代码遍历整个画布,输出每个位置的字符。

2.代码

dev c++ 5.11

#include<iostream>
#include<cstring>
using namespace std;
const int N=110;
int m,n,q;
void changePoint(int &x,int &y){
	int t=y;
	y=x;
	x=n-t-1;
}
char g[N][N];
bool st[N][N];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};


void dfs(int x,int y,char c){
	st[x][y]=true;
	g[x][y]=c;
	for(int i=0;i<4;i++){
		int a=x+dx[i],b=y+dy[i];
		if(a<0 || a>=n || b<0 || b>=m || st[a][b]) continue;
		if(g[a][b]=='-' || g[a][b]=='|' || g[a][b]=='+') continue;
		dfs(a,b,c);
	}
}



int main(){
	cin>>m>>n>>q;
	memset(g,'.',sizeof(g));
	while(q--){
		int op;
		cin>>op;
		if(op==0){
			int x1,y1,x2,y2;
			cin>>x1>>y1>>x2>>y2;
			changePoint(x1,y1);
			changePoint(x2,y2);
			if(x1==x2){
				for(int j=min(y1,y2);j<=max(y1,y2);j++){
					if(g[x1][j]=='|' || g[x1][j]=='+') g[x1][j]='+';
					else g[x1][j]='-';
				}
			}else{
				for(int i=min(x1,x2);i<=max(x1,x2);i++){
					if(g[i][y1]=='-' || g[i][y1]=='+') g[i][y1]='+';
					else g[i][y1]='|';
				}	
			}
		}else{
			int x,y;
			char c;
			cin>>x>>y>>c;
			changePoint(x,y);
			memset(st,false,sizeof(st));
			dfs(x,y,c);
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cout<<g[i][j];
		}
		cout<<endl;
	}
	return 0;
} 




3.提交结果

在这里插入图片描述

总结

1.解释

void dfs(int x,int y,char c){
	st[x][y]=true;
	g[x][y]=c;
	for(int i=0;i<4;i++){
		int a=x+dx[i],b=y+dy[i];
		if(a<0 || a>=n || b<0 || b>=m || st[a][b]) continue;
		if(g[a][b]=='-' || g[a][b]=='|' || g[a][b]=='+') continue;
		dfs(a,b,c);
	}
}

深度优先搜索(DFS),目的是扫描二维字符数组(g),并将连通块(由相同字符组成)替换为给定字符(c)。

具体来说,该函数的输入参数有三个:

  • x:当前搜索位置的行坐标;
  • y:当前搜索位置的列坐标;
  • c:用于替换连通块的字符。

在函数执行过程中,首先将当前搜索位置标记为已经访问过(通过bool数组st实现),并将其对应的字符改为给定字符c。然后,对于当前位置的四个相邻位置,如果该位置已经被访问过、或者是横线、竖线、加号中的任意一种字符,则直接跳过该位置不处理。否则继续递归搜索该位置,即调用dfs(a,b,c),其中a和b分别为当前位置的行列坐标。

在这个过程中,DFS会遍历所有与当前位置相连的可以访问到的位置,并将它们的字符替换为给定字符。具体实现中,DFS借助递归函数的方式,相当于将所有与当前位置连通的位置依次压入一个函数栈内,当遍历完当前连通块后再依次回溯,直到回溯到最初的调用位置,整个连通块的替换操作就完成了。

总体来说,该函数的作用是把二维字符数组中所有连通的相同字符替换为另一个指定字符。

2.其他

  1. 在if语句中,多了一些错误的等于符号“=”,应该使用双等号“==”来做相等判断。

  2. 在检查数组越界时,没有使用逻辑与运算符&&,而是使用错了单个的“=”等于号,所以if语句的条件判断失效了。

  3. 在对数组进行赋值时,对每个字符都使用了单引号而不是双引号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值