描述
(圖 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<iostream>
#include<stack>
#include<cstring>
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<<roomNum<<endl;
cout<<maxRoomArea<<endl;
return 0;
}
【解法二:堆棧】
/*這是一種仿照BFS模板的一種寫法,O(∩_∩)O哈哈~,現在我終於明白BFS和DFS(堆棧解法)的區別了,其實套用BFS的模板一樣可以實現DFS,說白了用堆棧寫的DFS和用隊列寫的BFS只有一點不同,那就是它們所用的數據結構不同,就是因爲這兩種不同的數據結構的不同特性,才使得深搜和廣搜效果不同。******堆棧爲後進先出,這使得每次遍歷時第一次也和廣搜一樣讀入的第一步能走的節點,接下來會以棧頂元素爲起點向下搜從該點一步能到的節點,但是每次查詢的一個元素都是此次遍歷的最後一個元素,也就是第二次查詢的都是起點能到的下一層元素。******隊列爲先進先出,每次遍歷時第一次也一樣讀入的第一步能走的節點,接下來會以隊首元素爲起點向下搜從該點一步能到的節點,但是每次查詢時都是先查詢一個元素都是上一層得元素,直到該層結束,在查下一層,因爲上一層元素總是先入隊的*/
//AC
#include<cstdio>
#include<cstring>
#include<stack>
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<data> 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+1<n&&!mark[p.x][p.y+1])
{
pp.x=p.x;
pp.y=p.y+1;
stk.push(pp);
}
if ((room[p.x][p.y]&8)==0&&p.x+1<m&&!mark[p.x+1][p.y])
{
pp.x=p.x+1;
pp.y=p.y;
stk.push(pp);
}
}
}
}
int main()
{
while (scanf("%d%d",&m,&n)!=EOF)
{
maxarea=0;
memset(mark,0,sizeof(mark));
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
scanf("%d",&room[i][j]);
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if (!mark[i][j])
{
area=0;
++num;
dfs(i,j);
if (area>maxarea)
maxarea=area;
}
}
}
printf("%d\n%d\n",num,maxarea);
}
return 0;
}
【解法三:其實這也是用堆棧解決的,只是裏面用的結構體內的構造函數,而不是兩個結構體變量】
#include <iostream>
#include <stack>
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<Room> 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 <<endl;
}