一個目的上下左右四個方向,稱之爲“氣”,如果一個目的四個方向都被某一種顏色的棋子佔據,那麼即使這個目上並沒有棋子,仍然認爲這個目被該顏色棋子佔據。
如下圖中,四個黑棋中心的交點,由於被黑棋包圍,因此我們認爲這個目屬於黑棋,
黑棋擁有4+1=5目
在棋盤的邊框地區,只要佔據目的三個方向,就可以擁有這個目。
黑棋擁有3+1=4目
同理在棋盤的四個角上,只要佔據目的兩個氣即可。
黑棋擁有2+1=3目
推而廣之,當有多個目互相連通的時候,如果能用一種顏色把所有交點的氣都包裹住,那麼就擁有所有目。
黑棋擁有6+2 = 8目
請編寫一個程序,計算棋盤上黑棋和白棋的目數。
輸入數據中保證所有的目,不是被黑棋包裹,就是被白棋包裹。不用考慮某些棋子按照圍棋規則實際上是死的,以及互相吃(打劫),雙活等情況。
輸入第一行,只有一個整數N(1<=N<=100),代表棋盤的尺寸是N * N
第2~n+1行,每行n個字符,代表棋盤上的棋子顏色。
“.”代表一個沒有棋子的目
“B”代表黑棋
“W”代表白棋
輸出只有一行,包含用空格分隔的兩個數字,第一個數是黑棋的目數,第二個數是白棋的目數。
樣例輸入
4 ..BW ...B .... ....樣例輸出
15 1
tips:這道題目的關鍵是通過什麼策略找到額外獲得‘目’,以黑棋爲例,先找到一個黑子,然後搜索他四周所有可獲得的目。
根據題設,不存在雙殺等特殊情況,因此統計次連通分量所有的個數即可。
#include<iostream>
#include<cstring>
using namespace std;
int n,cnt;
int book[222][222];
char mp[222][222];
int dire[][2]={-1,0,1,0,0,-1,0,1};
void dfs(int x,int y)
{
for(int i=0;i<4;i++)
{
int nx=x+dire[i][0];
int ny=y+dire[i][1];
if(nx<1||nx>n||ny<1||ny>n)continue;
if(!book[nx][ny]&&mp[nx][ny]=='.'){
book[nx][ny]=1;
cnt++;
dfs(nx,ny);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>mp[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(!book[i][j]&&mp[i][j]=='B')
{
cnt++;
book[i][j]=1;
dfs(i,j);
}
}
}
cout<<cnt<<" "<<n*n-cnt<<endl;
return 0;
}
PS:使用數組進行標記,dfs深搜;只算出黑色的,就可以得出白色的。並不需要完全包圍 啊。