哈理工OJ 1525 水神(海上葬禮)(【BFS(較困難)】)
地址:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1525
水神
Time Limit: 1000 MS Memory Limit: 16384 K
Total Submit: 16(5 users) Total Accepted: 6(4 users) Rating: Special Judge: No
Description
有一片被大海包圍的群島,島上居住著一個古老的部族。很多年前部落裡有一位巫師接受了水神的召喚跳入海中,從此,那一片海域就被打上了水神的烙印,被這片海域所包圍的陸地也被賦予了神聖的意義(包圍關係滿足傳遞性,即海域A包圍了島B,島B包圍了海域C,而海域C中包含了島D,則我們說海域A也包含了島D)。
從那以後,部落裡的巫師死後都必須葬在這片神聖海域所包圍的島上,而且每一個島都只能埋葬一位巫師(否則就會被視為對水神的不敬,從而給部族帶來災難)。現在給你群島的地圖和最初那位巫師跳海的地方,請你計算一下最多可以埋葬多少巫師。
地圖是一個n*m的字元矩陣,’#’代表陸地,’.’代表海洋。連通的一片陸地為一個島,連通的一片海洋為一個海域。其中,陸地從上、下、左、右4個方向連通,海洋從上、下、左、右、左上、左下、右上、右下8個方向連通。
如下圖。
圖中有4個島,2片海域。如果在A處落水,則落水的海域包圍了除右上、左下兩個頂角外的3個島嶼;如果在B處落水,則只包含了中間的2個島。
Input
有多組測試資料,不超過10組。
對於每組測試資料,輸入的第一行為n, m, x, y, n和m表示地圖的大小(1<=n,m<=500),x和y(0 <= x < n, 0 <= y < m)是巫師跳海的地方,資料保證巫師跳海的地方是一個水域。
接下來為一個n*m的字元矩陣,共n行,每行m個字元。
Output
對於每組測試資料,輸出一行,包含一個整數,為最多可以埋葬的巫師數量。
Sample Input
7 9 0 0
........#
.#######.
.#.....#.
.#.#.#.#.
.#.....#.
.#######.
#........
7 9 2 6
........#
.#######.
.#.....#.
.#.#.#.#.
.#.....#.
.#######.
#........
Sample Output
3
2
本題很難,不過或許對於你並不算難,但對於弱雞的我還是比較難的。
下面說下思路吧,首先搜一次,把最大的水域搜出來並標記上
void bfs1(int sx,int sy)
{
queue<node>q;
node fr,ne ;
fr.x=sx,fr.y=sy;
q.push(fr);
book1[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<8; i++)
{
ne.x=fr.x+dir[i][0];
ne.y=fr.y+dir[i][1];
if(a[ne.x][ne.y]=='.'&&ne.x>=0&&ne.x<n&&ne.y>=0&&ne.y<m&&book1[ne.x][ne.y]==0)
{
book1[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
接下來從第一行,最後一行,第一列,最後一列分別進行第二次搜尋,把最大水域外的區域全部搜出來。
void bfs2(int sx,int sy)
{
queue<node>q;
node fr,ne;
fr.x=sx,fr.y=sy;
q.push(fr);
book2[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<4; i++)
{
ne.x=fr.x+dir2[i][0];
ne.y=fr.y+dir2[i][1];
if(ne.x>=0&&ne.y>=0&&ne.x<n&&ne.y<m&&book2[ne.x][ne.y]==0&&book1[ne.x][ne.y]==0)
{
book2[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
下面進行第三次搜尋,第三次搜尋搜的是在最大水域裡面的連通塊的個數。因為第二次搜尋把不是最大水域裡的都標記出來了,第三次搜尋就非常簡單了,下面是第三次搜尋的程式碼:
void bfs3(int sx,int sy)
{
queue<node>q;
node fr,ne;
fr.x=sx,fr.y=sy;
q.push(fr);
book3[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<4; i++)
{
ne.x=fr.x+dir2[i][0];
ne.y=fr.y+dir2[i][1];
if(ne.x>=0&&ne.x<n&&ne.y>=0&&ne.y<m&&book3[ne.x][ne.y]==0&&a[ne.x][ne.y]=='#'&&book2[ne.x][ne.y]==0)
{
book3[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
下面是完整的AC程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
int x,y;
};
int n,m,dir[8][2]= {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
int sx,sy,book1[505][505],book2[505][505],book3[505][505],dir2[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
char a[500][500];
void bfs1(int sx,int sy)
{
queue<node>q;
node fr,ne;
fr.x=sx,fr.y=sy;
q.push(fr);
book1[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<8; i++)
{
ne.x=fr.x+dir[i][0];
ne.y=fr.y+dir[i][1];
if(a[ne.x][ne.y]=='.'&&ne.x>=0&&ne.x<n&&ne.y>=0&&ne.y<m&&book1[ne.x][ne.y]==0)
{
book1[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
void bfs2(int sx,int sy)
{
queue<node>q;
node fr,ne;
fr.x=sx,fr.y=sy;
q.push(fr);
book2[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<4; i++)
{
ne.x=fr.x+dir2[i][0];
ne.y=fr.y+dir2[i][1];
if(ne.x>=0&&ne.y>=0&&ne.x<n&&ne.y<m&&book2[ne.x][ne.y]==0&&book1[ne.x][ne.y]==0)
{
book2[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
void bfs3(int sx,int sy)
{
queue<node>q;
node fr,ne;
fr.x=sx,fr.y=sy;
q.push(fr);
book3[sx][sy]=1;
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0; i<4; i++)
{
ne.x=fr.x+dir2[i][0];
ne.y=fr.y+dir2[i][1];
if(ne.x>=0&&ne.x<n&&ne.y>=0&&ne.y<m&&book3[ne.x][ne.y]==0&&a[ne.x][ne.y]=='#'&&book2[ne.x][ne.y]==0)
{
book3[ne.x][ne.y]=1;
q.push(ne);
}
}
}
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&sx,&sy))
{
int sum=0;
for(int i=0; i<n; i++)
{
scanf("%s",&a[i]);
}
memset(book1,0,sizeof(book1));
memset(book2,0,sizeof(book2));
memset(book3,0,sizeof(book3));
bfs1(sx,sy);
for(int i=0; i<n; i++)
{
if(book1[0][i]==0)
{
bfs2(0,i);
}
}
for(int i=0; i<n; i++)
{
if(book1[n-1][i]==0)
{
bfs2(n-1,i);
}
}
for(int i=0; i<m; i++)
{
if(book1[i][0]==0)
{
bfs2(i,0);
}
}
for(int i=0; i<m; i++)
{
if(book1[i][m-1]==0)
{
bfs2(i,m-1);
}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(a[i][j]=='#'&&book2[i][j]==0&&book3[i][j]==0)
{
sum++;
bfs3(i,j);
}
}
}
printf("%d\n",sum);
}
return 0;
}