百練-3723圍棋

原文

描述圍棋的棋盤上有19*19條線交織成的361個交點,黑棋和白棋可以下在交點上。我們稱這些交點爲“目”。

一個目的上下左右四個方向,稱之爲“氣”,如果一個目的四個方向都被某一種顏色的棋子佔據,那麼即使這個目上並沒有棋子,仍然認爲這個目被該顏色棋子佔據。

如下圖中,四個黑棋中心的交點,由於被黑棋包圍,因此我們認爲這個目屬於黑棋,

黑棋擁有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深搜;只算出黑色的,就可以得出白色的。並不需要完全包圍 啊。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章