1. 程式人生 > >ccf真題-201512-3-畫圖AC題解

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
// CSDN blog address   :    http://blog.csdn.net/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;



——————————————————————————————