城堡问题Poj(1164)

Description

     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.

Input

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.

Output

Your program is to write to standard output: First the number of rooms, then the area of the largest room (counted in modules).

Sample Input

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

Sample Output

5
9

题目是要编写一个程序,来计算城堡一共有多少个房间,最大的房间有多大. 城堡被分为 m * n 个方块 ,每一个方块有 0~ 4 面墙 ."#"代表墙壁, "|" 和 "-"代表没有墙壁 , 不被墙分隔的方块连在一起组成一个房间.城堡外围一圈都是墙 .

输入数据 

第一行 n,m ,分别是南北向,东西向的方块数 .

接下来是一个n 行 m列的整数矩阵,每个整数p描述一个方块,如果用1 代表西墙 , 2代表北墙 ,4 代表东墙 ,8 代表南墙 ,则用来描述一个方块的整数,其值就是该方块周围每个墙所对应的数字之和 . 例如,某方块有南墙和北墙 ,则描述他的整数就是 2 +8 =10 .某方块四面都是墙 ,则描述他的整数就是 1+2+4+8 = 15 .

输出

城堡的房间数,以及城堡中最大房间所包括的方块数. 

解题思路 :

               可以把方块看成节点,那么相邻两个方块之间如果没有墙,则在方块之间连一条边, 这样就可以把城堡转换成了一个图,求房间的个数,实际上就是求图中有多少个极大连通子图,向一个连通子图中加入任何一个图中的点,连通子图就会变得不连通,那么这样的连通子图就是极大连通子图,求城堡的最大房间有几块方块,就是求最大的那个极大连通子图包含几个节点.

                按照深搜的算法,从一个新节点出发,就能求出该节点所在的极大连通子图,并且将子图中的所有节点标记为已经访问过的点,然后在找一个新节点,就能找到一个极大连通子图.因此,可以用dfs来求解.具体的解法可以描述为 : 对于每一个房间进行深度有限搜素,从而给房间包含的所有节点(方块)染色,给方块染色就是在图中将节点标记为已访问过.找到一个房间就换一种颜色,最后统计用了几种颜色,就是有几个房间, 颜色的个数表示房间的大小,

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std ;
const int MAXN = 60 ;
int R ,C ;
int room[MAXN][MAXN] ; // 存放代表每个方块的整数
int color[MAXN][MAXN] ; // 每个房间染的颜色 , 0 表示为染过颜色
int maxRoomArea = 0 ; // 最大房间面积
int colorNum = 0 ; // 颜色的编号 ;
int roomArea  ; // 当前正在染色的房间的面积;
void dfs(int i ,int k)
{
	if(color[i][k])
	{// 如果染过色就返回; // 出栈
		return ;
	}
	roomArea++ ;
	color[i][k] = colorNum ; // 给方块染色;
	if( (room[i][k] & 1 ) == 0 ) dfs(i,k-1) ; // 向西走 ;
	if( (room[i][k] &2  ) == 0 ) dfs(i-1,k) ;
	if( (room[i][k] &4  ) == 0 ) dfs(i,k+1) ;
	if( (room[i][k] &8 )  == 0 ) dfs(i+1,k) ;
	return ;
}
int main()
{
//	freopen("in.txt","r",stdin);
	cin >>R >> C ;
	for (int i = 1 ; i<=R ; i++)
	{
		for(int k = 1 ;k <=C ;k++)
		{
			cin >>room[i][k] ;
		}
	}
	memset(color , 0 ,sizeof(color));
	for(int i = 1 ; i<= R ; i++)
	{
		for(int k = 1 ; k<=C ;k++)
		{
			if(!color[i][k])
			{
				// 如果还没走过
				++colorNum ;
				roomArea =  0 ;
				dfs( i, k);
				maxRoomArea = max(roomArea,maxRoomArea) ;
			}
		}
	}
/*	for(int i = 1 ; i <=R ;i++)
	{
		for(int j =1 ; j<=C; j++)
		{
			cout<<color[i][j]<<" ";
		}
		cout<<endl;
	}*/
	cout<<colorNum<<endl;
	cout<<maxRoomArea<<endl;
	
	return 0 ;
}


// 栈模拟递归
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std ;
const int MAX = 100 ;
int room[MAX][MAX] ;
int color[MAX][MAX] ;
int n , m ;
int roomNum ;
int MAXroomArea ;
int roomArea ;
struct Room{
	int r ;
	int c ;
	Room(int rr,int cc) :r(rr),c(cc){}

};
void dfs(int i ,int j )
{
	stack<Room> stk ;
	stk.push(Room(i,j));
	while(!stk.empty())
	{
		Room rm = stk.top();
		int t1 = rm.r ;
		int t2 = rm.c ;
		if(color[t1][t2])
		stk.pop();

	
//	if(color[i][j])
//	return ;
else{
	

	color[i][j] = roomNum ; // 染色;
	roomArea++ ;
	if( (room[i][j]  &1  ) == 0 ) dfs(i,j-1) ;// 向西走
	if( (room[i][j]  &2  ) == 0 ) dfs(i-1,j) ; //bei
	if( (room[i][j]  &4  ) == 0 ) dfs(i,j+1) ;
	if( (room[i][j]  &8  ) == 0 ) dfs(i+1,j) ;
}
}
	
	return ;
}
int main()
{
//	freopen("in.txt","r",stdin);
	cin >> n>>m ;
	for(int i = 1 ; i<= n ; i++)
	{
		for(int j = 1 ; j<=m ;j++)
		{
			cin >>room[i][j] ;
		}
	}
	for(int i = 1 ; i<=n ;i++)
	{
		for(int j = 1 ; j <=m ;j++)
		{
			if(!color[i][j])
			{
				++roomNum ; //编号
				roomArea = 0 ;
				dfs(i,j); // 对该顶点进行访问;
				MAXroomArea = max(roomArea,MAXroomArea);
			}
		}
	}
	cout << roomNum<<endl;
	cout<< MAXroomArea <<endl;

	
	
	
	return 0 ;
}

参考 << 算法基础与在线实践>> 

猜你喜欢

转载自blog.csdn.net/qq_41661809/article/details/81288860