ccf真题-201512-3-画图AC题解

1.题目: 画图-题目


2.输入输出:

输入:第一行-宽度、高度、操作数

在每个操作中:① 0 起止坐标 ② 1 起始坐标 填充字符

输出:依次执行操作后的画图结果


3.题目分析:看起来题目很花,但是只要把每个部分拆开来卡就好了,输入输出以及数组的初始化成小数点,很简单。

判断操作是划线还是填充,根据每行的第一个数字就OK,也很简单。

如何划线和填充呢?划线无非是横坐标相同则画竖线,纵坐标相同画横线。填充就运用递归。需要注意的是,画线时要考虑到如果已经有线了怎么办?如何避免一个格子反复被递归调用到?


4.AC代码:

// ============================================================================
// File Name           :    ccf真题-201512-3-画图AC代码.cpp
// Author              :    Sneexy
// Create Time         :    2017/03/11 14:48:49
// Update Time         :    2017/03/11 14:48:49
// 优快云 blog address   :    http://blog.youkuaiyun.com/qq_33810513
// ============================================================================
#include 
  
  
   
   
#include
   
   
    
    
using namespace std;
int line, row;
char point[105][105];
void fill(int i, int j, char ch)
{
	if (point[i][j]==ch || point[i][j] == '-' || point[i][j] == '|' || point[i][j] == '+')return;
	point[i][j] = ch;
	if (j)fill(i,j-1 ,ch);//左
	if (j < line - 1)fill(i,j+1, ch);//右
	if (i)fill(i-1, j , ch);//上
	if (i < row - 1)fill(i+1, j , ch);//下
	return;
}
int main()
{
	int i, j,k;//临时变量
	int cinNum, flag, posx, posy,posx1,posy1;//cinNum-输入组数;flag-操作类型:0-划线,1 - 填充
	char  ch;
	cin >> line >> row >> cinNum;
	for (i = 0; i < row; i++)//  1.将矩阵初始化为小数点
	{
		for (j = 0; j < line; j++)point[i][j] = '.';
	}
	while (cinNum--)//  2.根据输入数据进行操作
	{
		cin >> flag;
		if (flag == 1)
		{
			cin >> posx >> posy >>  ch;
			fill(row-1-posy, posx, ch);//  2.1循环遍历上下左右,填充
		}	
		if (!flag)  //2.2 根据两点坐标划线
		{
			cin >> posx >> posy >> posx1 >> posy1;
			if (posx == posx1)//竖线
			{
				if (posy > posy1){ k = posy; posy = posy1; posy1 = k; }
				for (i = posy; i <= posy1; i++)
				{	//通过分析可知最终结果只有 + | 两种
					if (point[row - 1 - i][posx] == '-' || point[row - 1 - i][posx] == '+')point[row - 1 - i][posx] = '+';
					else point[row - 1 - i][posx] = '|';
				}
			}
			else if (posy==posy1)//横线
			{
				if (posx > posx1){ k = posx; posx = posx1; posx1 = k; }
				for (i = posx; i <= posx1; i++)
				{	//通过分析可知最终结果只有 + - 两种
					if (point[row - 1 - posy][i] == '|' || point[row - 1 - posy][i] == '+')point[row - 1 - posy][i] = '+';
					else point[row - 1 - posy][i] = '-';
				}
			}
		}
	}
	for (i = 0; i < row; i++)//	3.输出矩阵
	{
		for (j = 0; j < line; j++) cout << point[i][j];
		cout << endl;
	}
	return 0;
}
   
   
  
  


5.解题记录:

重点:——输入的flag会影响后面的赋值,但是flag跟后续的数同一行输入对结果无影响;
——输入的数据如果是两个int,一个char,通过cin>>intA>>intB>>charC;是可以对char
    正确赋值的,输入时直接“1 2 a”就行
——判断条件很重要,而且要理清思路,题目中的i、row是从上到下的行,
    j、line、posx是从左到右的列,posy是从下到上的行。
————————————————————————————————————————————————————————————————
用此程序说明了输入flag和后续的根据flag输入的数据,由同一行输入进去是可行的:
#include 
   
   
    
    
using namespace std;
int main()
{
	int a, b, c, d;
	int t = 100;
	while (t--)
	{
		cin >> a;
		if (a == 1)
		{
			cin >> b >> c;
			cout << "b,c:  " << b << "  " << c << endl;
		}
		if (a == 2)
		{
			cin >> d;
			cout << "d:  " << d << endl;
		}
	}
	return 0;
}
1 2 3
b,c:  2  3
2 2
d:  2
1 2
2
b,c:  2  2


样例:
3 4 2
1 0 0 b
0 1 0 2 0
发现不能进行继续的输入程序就运行完了,猜测是由于递归未进行完全的缘故,将
if (point[posx][posy] == '-' || point[posx][posy] == '|' || point[posx][posy] == '+')return;  
改为    if(point[posx][posy] != '.')return;
否则如果是已经被填充了的仍然会一直进行填充,修改后可以完整输入了。


——————————————————————————————————————————————————————————————————
出现问题是,该输出的区域没有输出,为空白,猜测是因为字符不可以通过等于符号赋值,
通过以下代码否定此猜测:
char arr[5][5];
	for (int i = 0; i < 5;i++)
	{
		for (int j = 0; j < 5;j++)
		{
			arr[i][j] = 'a';
		}
	}
	arr[3][3] = 'b';
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			cout << arr[i][j] << " ";
		}cout << endl;
	}

——————————————————————————————————————
找出原因是:将输入line、row放在了循环操作初始化前面,导致初始化出错。
后发现输入是int int char类型“0 0 b”的时候,char数据会被赋值为b而不是空格。


递归时用if(point[posx][posy] != '.')return;  会导致已经被赋值过的位置无法在另外一行填充中使用,
故改为:if (point[i][j]==ch || point[i][j] == '-' || point[i][j] == '|' || point[i][j] == '+')return;


   
   


——————————————————————————————
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值