試題編號: | 201803-4 |
試題名稱: | 棋局評估 |
時間限制: | 1.0s |
內存限制: | 256.0MB |
問題描述: |
問題描述 Alice和Bob正在玩井字棋遊戲。 輸入格式 輸入的第一行包含一個正整數T,表示數據的組數。 輸出格式 對於每組數據,輸出一行一個整數,表示當前局面的得分。 樣例輸入 3 樣例輸出 3 樣例說明 第一組數據: 數據規模和約定 對於所有評測用例,1 ≤ T ≤ 5。 |
答題思路:用DFS模擬兩個人下棋的過程,到Alice下棋的時候,Alice可以在棋盤的所有空格中選擇一處進行落子,我們找出Alice所有落子中得分最大的那次落子,Bob也類似。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int a[3][3];
//統計還有多少個地方可以落子
int countEmpty(){
int cnt = 0;
//遍歷棋盤的每一格
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(a[i][j] == 0){ //此處還沒有被落子過
cnt++;
}
}
}
return cnt;
}
//判斷當前情況誰是勝利者。返回值:1--Alice勝利,2--Bob勝利,0--暫時未分勝負
int judgeWinner(){
int result;
//某一行是否有三個相同的棋子。
for(int i=0;i<3;i++){
if(a[i][0] == a[i][1] && a[i][0] == a[i][2] && a[i][0] != 0){
result = a[i][0]==1?1:2;
return result;
}
}
//某一列是否有三個相同的棋子。
for(int i=0;i<3;i++){
if(a[0][i] == a[1][i] && a[0][i] == a[2][i] && a[0][i] != 0){
result = a[0][i]==1?1:2;
return result;
}
}
//兩條對角線是否有三個相同的棋子。
if(a[0][0] == a[1][1] && a[0][0] == a[2][2] && a[0][0] != 0){
result = a[0][0]==1?1:2;
return result;
}
if(a[0][2] == a[1][1] && a[0][2] == a[2][0] && a[0][2] != 0){
result = a[0][2]==1?1:2;
return result;
}
return 0;
}
int DFS2();
//Alice落子
int DFS1(){
int winner = judgeWinner();
if(winner != 0){ //有人贏了
if(winner == 1){ //Alice贏了
return countEmpty() + 1; //返回Alice的得分。
}else{ //Bob贏了
return -1*countEmpty() - 1; //返回Bob的得分
}
}
if(countEmpty() == 0){ //如果棋盤已經無處落子了。
return 0;
}
//尋找在何處落子
int ans = -5;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(a[i][j] == 0){ //此處還沒有被落子過
a[i][j] = 1; //假設Alice選擇此處落子
int now = DFS2(); //輪到Bob落子
ans = max(now,ans);
a[i][j] = 0; //相當於悔棋,要重新選擇一處進行落子
}
}
}
return ans;
}
//Bob落子
int DFS2(){
int winner = judgeWinner();
if(winner != 0){ //有人贏了
if(winner == 1){ //Alice贏了
return countEmpty() + 1; //返回Alice的得分。
}else{ //Bob贏了
return -1*countEmpty() - 1; //返回Bob的得分
}
}
if(countEmpty() == 0){ //如果棋盤已經無處落子了。
return 0;
}
//尋找在何處落子
int ans = 5;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(a[i][j] == 0){ //此處還沒有被落子過
a[i][j] = 2; //假設Bob選擇此處落子
int now = DFS1(); //輪到Alice落子,now的值是:如果下到此處,該盤棋的最終得分。
ans = min(ans,now);//在所有得分中選一個最小得分。
a[i][j] = 0; //相當於悔棋,要重新選擇一處進行落子
}
}
}
return ans;
}
int main(){
int n;
cin>>n;
while(n--){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cin>>a[i][j];
}
}
if(countEmpty() == 9){
cout<<"0"<<endl;
}else{
cout<<DFS1()<<endl;
}
}
return 0;
}