城堡问题

/*
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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值