试题编号: | 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;
}