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;
——————————————————————————————