華為機試—圍棋吃子(下圍棋)判決(進階題160分:深度優先遍曆)(圖文吐血整理)

來源:互聯網
上載者:User

標籤:華為機試   圍棋吃子   下圍棋   深度優先遍曆   

題目:

圍棋中,一個棋子在棋盤上,與它直接緊鄰的空點是這個棋子的“氣”,棋子直接緊鄰的點上,如果有同色妻子存在,則它們便相互組成一個不可分割的整體,它們的“氣”也應一併計算。如果一個或一片棋子的“氣”為0,那它們將被吃掉。

1. 一個棋子的情況,如下左圖,白棋右側還有一個空點,此時白棋氣為1,不會被吃掉。當黑棋在此空點下棋後,白棋氣為0,將被吃掉。


2. 一片棋子的情況,如,左下角的白棋下面有一個空點,由於其它白棋都與之能通過直接相鄰,此時整片白棋的氣都為1,不會被吃掉。當黑棋在該空點下棋後,白棋氣為0,將被吃掉。


3. 當下棋造成雙方棋子都沒有氣時,只有對方的棋子被吃掉。如空點處,黑棋下子後,最中間的黑棋和中圈的白棋都沒有氣,但只有白棋被吃掉。除了這種情況。不允許下棋導致本方棋子沒有氣(自殺棋)。



本題用一個10x10的二維數組表示棋盤,數組中0表示空點,1表示白棋,2表示黑棋 。棋盤左下角為(0,0),右上方為(9,9),水平為x方向,豎直為y方向。

為避免走棋步數太多,提供設定棋盤的介面可以將棋盤初始化為一個殘局狀態。之後不斷進行下棋,下棋順序不定,可以連續下黑或者連續下白(圍棋允許一方放棄下子)當棋子吃掉後,返回相應的吃子情況外,還應將被吃棋子從棋盤中移除,保證棋盤狀態正確。


已耗用時間限制:無限制


記憶體限制:無限制


輸入:輸入一個10*10的整數,初始化棋盤。輸入保證初始化的殘局中不存在氣為0的子(即被吃棋子卻沒取走的異常狀態)。輸入一行或多行整數,每行3個整數,分別表示,所下棋子的x位置,y位置,棋子類型(1表示白棋,2表示黑棋)。


輸出:一個整數。含義如下:

0:本次下棋未發生吃子

2147483647下棋錯誤(該位置已有棋子,或下棋導致本方棋子無氣)

其餘正值:有白棋被吃掉,吃掉個數等於返回值

負值:有黑棋被吃掉,吃掉個數等於返回值的絕對值


解析:

當給定一個輸入時,我們首先判斷下的這個棋子是否導致自身的棋子沒氣;然後判斷下的這個棋子是否導致對方的棋子沒氣,並統計沒氣的棋子的個數;若對方沒有棋子沒氣,但自身有棋子沒氣了,則為違規輸入;否則,返回對方沒氣的棋子的個數即可。

那麼這裡關鍵問題便是如何判斷是否有棋子沒氣了。這個問題可以用典型的dfs(深度優先)的方法來解決。給定一個位置以及該位置的棋子類型,我們首先判斷該棋子上方是否為空白,若為空白,則表示與該棋子位置相連的相同棋子均有氣;若上方棋子為相同顏色的棋子,則遞迴到該位置繼續判斷;若上方位置為對方棋子,則表示該棋子上方沒有氣。在遍曆玩該棋子的上方能夠遍曆的位置之後,發現沒有找到氣,則選擇其他方向繼續遍曆。直到一個方向找到了氣,或是四個方向均沒有氣。


#include <iostream>  using namespace std;    int A[10][10] =   {      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 2, 0, 0, 0, 0, 0,      0, 0, 0, 2, 1, 2, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0  };  bool B[10][10];  int eatCount = 0;    //初始化矩陣B都為false void initFlagMatrix()  {      for(int i = 0; i < 10; i++)      {          for(int j = 0; j < 10; j++)               B[i][j] = false;      }  }    bool hasAir(int i, int j, int type)  {      if(A[i][j] == 0) return true;      if(A[i][j] != type) return false;      eatCount++;     B[i][j] = true;      if(i > 0 && !B[i-1][j] && hasAir(i-1, j, type)) return true;      else if(i < 9 && !B[i+1][j] && hasAir(i+1, j, type)) return true;      else if(j > 0 && !B[i][j-1] && hasAir(i, j-1, type)) return true;      else if(j < 9 && !B[i][j+1] && hasAir(i, j+1, type)) return true;      else return false;  }    //將與A[i][j]相連的相同類型的棋子全部吃掉  void eatChess(int i, int j, int type)  {      if(A[i][j] != type) return;      A[i][j] = 0;    //吃掉子    if(i > 0) eatChess(i-1, j, type);      if(i < 9) eatChess(i+1, j, type);      if(j > 0) eatChess(i, j-1, type);      if(j < 9) eatChess(i, j+1, type);  }    //尋找整個棋盤看棋子是否有氣  bool hasAirOfType(int type, int &p, int &q)  {      for(int i  = 0; i < 10; i++)      {          for(int j = 0; j < 10; j++)          {              if(A[i][j] != type || B[i][j]) continue;               eatCount = 0;              if(!hasAir(i, j, type))               {                  p = i, q = j;                  return false;              }          }      }      return true;  }  //當位置[i,j]放個黑白子的時候吃掉子的個數  int eatenChesscount(int i, int j, int type)  {      initFlagMatrix();      bool self_hasAir = hasAir(i, j, type);      eatCount = 0;      int p = 0, q = 0;      int other_type = (type==1?2:1);      initFlagMatrix();      bool other_hasAir = hasAirOfType(other_type, p, q);        if(!self_hasAir && other_hasAir)//自殺    {          A[i][j] = 0;          return 2147483647;     }      if(!other_hasAir)      {          eatChess(p, q, other_type);          if(other_type == 1) //白子正數return eatCount;          else                //黑子負數return 0-eatCount;      }      return 0;  }  //列印10*10矩陣的殘局狀態void printChessState()  {      for(int i = 0; i < 10; i++)      {          for(int j = 0; j < 10; j++)          {              cout << A[i][j] << " ";          }          cout << endl;      }  }    int main()  {      int i, j, type;      while(cin >> i >> j >> type)      {          if(A[i][j] != 0)          {              cout << "2147483647" << endl;              continue;          }          A[i][j] = type;cout<<"當前的殘局狀態:"<<endl;        printChessState();          cout << "此次吃子個數:"<< eatenChesscount(i, j, type) << endl;  cout<<"吃子後殘局狀態"<<endl;        printChessState();      }  return 0;} 






華為機試—圍棋吃子(下圍棋)判決(進階題160分:深度優先遍曆)(圖文吐血整理)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.