描述
(图 1)
# = Wall
| = No wall
- = No wall
图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成m*n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。
输入
程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。
输出
城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。
样例输入
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
例:11的二进制为1011,每一位二进制分别表示“南墙”“东墙”“北墙”“西墙”,为1表示有墙,为0表示没墙。
按位与运算符&的使用:如:11&4 <=> 1011 & 0100 = 0000 = 0。相同为1,不同为0。
竖式:1011
&0100
-----
0000
解题思路:
对每个方块,深度优先搜索(DFS),从而给这个方块能够达到的所有位置染色。最后统计出一共有多少种颜色,以及每种颜色的数量。
比如:
1 1 2 2 3 3 3
1 1 1 2 3 4 3
1 1 1 5 3 5 3
1 5 5 5 5 5 3
从而一共有5个房间,最大的房间(1)占据9个格子。
【解法一:递归】
//AC
#include
#include
#include
using namespace std;
int R,C; //行列数
int rooms[60][60];
int color[60][60]; //房间是否染色过的标记
int maxRoomArea=0,roomNum=0;
int roomArea;
//用递归解决:
void Dfs(int i,int k)
{
if (color[i][k])
return ;
++roomArea;
color[i][k]=roomNum;
if ((rooms[i][k]&1)==0)
Dfs(i,k-1); //向左走
if ((rooms[i][k]&2)==0)
Dfs(i-1,k); //向上走
if ((rooms[i][k]&4)==0)
Dfs(i,k+1); //向右走
if ((rooms[i][k]&8)==0)
Dfs(i+1,k); //向下走
}
int main()
{
cin>>R>>C;
for (int i=1;i<=R;i++)
for (int k=1;k<=C;k++)
cin>>rooms[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])
{
++roomNum;
roomArea=0;
Dfs(i,k);
maxRoomArea=max(roomArea,maxRoomArea);
}
}
}
cout<
【解法二:堆栈】
/*这是一种仿照BFS模板的一种写法,O(∩_∩)O哈哈~,现在我终于明白BFS和DFS(堆栈解法)的区别了,其实套用BFS的模板一样可以实现DFS,说白了用堆栈写的DFS和用队列写的BFS只有一点不同,那就是它们所用的数据结构不同,就是因为这两种不同的数据结构的不同特性,才使得深搜和广搜效果不同。******堆栈为后进先出,这使得每次遍历时第一次也和广搜一样读入的第一步能走的节点,接下来会以栈顶元素为起点向下搜从该点一步能到的节点,但是每次查询的一个元素都是此次遍历的最后一个元素,也就是第二次查询的都是起点能到的下一层元素。******队列为先进先出,每次遍历时第一次也一样读入的第一步能走的节点,接下来会以队首元素为起点向下搜从该点一步能到的节点,但是每次查询时都是先查询一个元素都是上一层得元素,直到该层结束,在查下一层,因为上一层元素总是先入队的*/
//AC
#include
#include
#include
using namespace std;
int mark[60][60];
int room[60][60];
int n,m,num=0,area,maxarea;
struct data
{
int x,y;
};
void dfs(int x,int y)
{
stack stk;
data p,pp;
p.x=x;
p.y=y;
stk.push(p);
while (!stk.empty())
{
p=stk.top();
if (mark[p.x][p.y])
stk.pop();
else
{
++area;
mark[p.x][p.y]=1;
if ((room[p.x][p.y]&1)==0&&p.y>0&&!mark[p.x][p.y-1])
{
pp.x=p.x;
pp.y=p.y-1;
stk.push(pp);
}
if ((room[p.x][p.y]&2)==0&&p.x>0&&!mark[p.x-1][p.y])
{
pp.x=p.x-1;
pp.y=p.y;
stk.push(pp);
}
if ((room[p.x][p.y]&4)==0&&p.y+1maxarea)
maxarea=area;
}
}
}
printf("%d\n%d\n",num,maxarea);
}
return 0;
}
#include
#include
using namespace std;
int m, n, roomNum = 0, curRoomAera;
int map[50][50], color[50][50] = {0};
struct Room
{
int x, y;
Room(int x, int y):x(x),y(y) {}
};
//用栈解决:
void dfs(int X, int Y)
{
stack stk;
stk.push(Room(X, Y));
int x, y;
while (!stk.empty())
{
Room topRoom = stk.top();
x = topRoom.x;
y = topRoom.y;
if (color[x][y])
stk.pop();
else
{
curRoomAera++;
color[x][y] = roomNum; //标记栈顶元素
//坑爹啊......&(按位与)运算符的优先级小于 == ,所以必须加括号
if (((map[x][y] & 1) == 0) && (y > 0) && !color[x][y-1]) //千万注意!&1==0时对应的一定是y-1,即必须向左走
stk.push(Room(x, y-1));
if (((map[x][y] & 2) == 0) && (x > 0) && !color[x-1][y]) //千万注意!&2==0时对应的一定是x-1,即必须向上走
stk.push(Room(x-1, y));
if (((map[x][y] & 4) == 0) && (y+1 < n) && !color[x][y+1]) //千万注意!&4==0时对应的一定是y+1,即必须向右走
stk.push(Room(x, y+1));
if (((map[x][y] & 8) == 0) && (x+1 < m) && !color[x+1][y]) //千万注意!&8==0时对应的一定是x+1,即必须向下走
stk.push(Room(x+1, y));
}
}
}
int main()
{
int maxRoomAero = 0;
cin >> m >> n;
for( int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> map[i][j];
for( int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (!color[i][j])
{
roomNum++;
curRoomAera = 0;
dfs(i, j);
if (curRoomAera > maxRoomAero)
maxRoomAero = curRoomAera;
}
cout << roomNum << endl << maxRoomAero <