城堡問題

/*
1164:The Castle
總時間限制: 1000ms 內存限制: 65536kB
描述
     1   2   3   4   5   6   7  
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #
   #---#########---#####---#---#
 4 #   #   |   |   |   |   #   #
   #############################
(Figure 1)

#  = Wall   
|  = No wall
-  = No wall

Figure 1 shows the map of a castle.Write a program that calculates
1. how many rooms the castle has
2. how big the largest room is
The castle is divided into m * n (m<=50, n<=50) square modules. Each such module can have between zero and four walls. 
輸入
Your program is to read from standard input. The first line contains the number of modules in the north-south direction and the number of modules in the east-west direction. In the following lines each module is described by a number (0 <= p <= 15). This number is the sum of: 1 (= wall to the west), 2 (= wall to the north), 4 (= wall to the east), 8 (= wall to the south). Inner walls are defined twice; a wall to the south in module 1,1 is also indicated as a wall to the north in module 2,1. The castle always has at least two rooms.
輸出
Your program is to write to standard output: First the number of rooms, then the area of the largest room (counted in modules).
樣例輸入
4
7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
樣例輸出
5
9
來源
IOI 1994
解題總結:
本題主要思路就是從每一個點的四個方向開始搜索,如果可以走通的話就將該處的位置標記爲與之具有相同標號
一個搜索完畢後,就令編號加一
因爲牆是用1,2,4,8記錄的,很容易讓人聯想到通過按位與來測量該點的各個方向是否有牆
搜索完畢後,即得房間數,再遍歷標記,找出最大的房間號
編寫過程中失誤的地方:
1.memset(room,0,sizeof(CurId)),CurId是指針,而非數組名,sizeof(CurId) = 4 而非數組字節數,應爲memset(room,0,sizeof(int)*CurId);
2.編寫mark函數時,對於x,y到底是指那個方向時沒有弄清楚,導致搜索方向錯誤
3.判斷邊界條件時,除了x,y不超過邊界時,如果已標記,就不用再標記了
  關鍵是已標記並不是Mark[x][y] == 1	而應該是Mark[x][y] != 0	,否則就導致了循環標記,陷入死循環
*/
#include<iostream>
#include<cstring>
using namespace std;
int r,c;
int **Data,**Mark;
void mark(int x,int y,int Id)
{
	if(x < 0 || x >= r || y < 0 || y >= c || Mark[x][y] != 0)
		return;
	Mark[x][y] = Id;
	//巧用按位與,==0則表示該方向沒有牆,進入搜索
	if((Data[x][y] & 0x01) == 0)	//search west
		mark(x,y-1,Id);
	if((Data[x][y] & 0x02) == 0) //search north
		mark(x-1,y,Id);
	if((Data[x][y] & 0x04) == 0) //search east
		mark(x,y+1,Id);
	if((Data[x][y] & 0x08) == 0) //search south
		mark(x+1,y,Id);
}
void Work()
{
	cin >> r >> c;
	int i,j,CurId = 1;
	Data = new int* [r];
	Mark = new int* [r];
	for(i = 0; i < r; ++i)
	{
		Data[i] = new int [c];
		Mark[i] = new int [c];
		for(j = 0; j < c; ++j)
			cin >> Data[i][j];
		memset(Mark[i],0,sizeof(int)*c);
	}
	for(i = 0; i < r; ++i)			//開始深度搜索,調用mark函數
		for(j = 0; j < c; ++j)
		{
			if(Mark[i][j] == 0)
			{
				mark(i,j,CurId);
				++CurId;
			}
		}
	//遍歷尋找最大的房間,和總共的房間數
	int rMax = -1,*room;
	room = new int [CurId];
	memset(room,0,sizeof(int)*CurId);
	for(i = 0; i < r; ++i)
		for(j = 0; j < c; ++j)
			++room[Mark[i][j]];
	for(i = 0; i < CurId; ++i)
		if(rMax < room[i])
			rMax = room[i];
	cout << CurId - 1 << endl << rMax << endl;
	//釋放內存空間
	for(i = 0; i < r; ++i)
	{
		delete Mark[i];
		delete Data[i];
	}
	delete [] room;
	delete [] Data;
	delete [] Mark;
}
int main()
{
	Work();
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章