Problem A: Tic Tac Toe
![](http://uva.onlinejudge.org/external/116/p11623.png)
Your task is to analyze the state of a Tic Tac Toe board, and determine whether the game is still in progress, or if it has completed, who won, or if the game ended in a draw. You should also detect erroneous states of the Tic Tac Toe board that could never occur during an actual game.
Input Specification
The first line of input contains a single integer, the number of test cases to follow. The first line of each test case contains the two integers n and m, separated by spaces, with 1 <= m <= n <= 1000. The following n lines of the test case each contain one row of the Tic Tac Toe board. Each of these lines contains exactly n characters, and each of these characters is either an X, an O, or a period ( .), indicating an empty square.Sample Input
1 3 3 ..X OOX ..X
Output Specification
For each test case, output a single line containing the appropriate string X WINS, O WINS, or DRAW if the game is over, the string IN PROGRESS if the game has not yet finished, or ERROR if the state of the board could never occur during a game.Output for Sample Input
X WINS
这题关键是ERROR的情况,我总结如下: 1、'X'出现的比'O'少,则输出ERROR; 2、'X'出现次数和'O'出现次数相差超过1,则输出ERROR; 3、'X'和'O'都赢了,,则输出ERROR; 4、'X'赢的时候,'X'出现的次数和'O'出现次数相差不是1,则输出ERROR;(因为'X'是先手) 5、赢者连续的长度必须 < 2*m,否则输出ERROR;(因为>=2*m的话,说明之前就已经赢了,然后结束了) 6、若赢者有多个长度满足要求必定交于一点,而且交点两边的长度一定要 < m,否则输出ERROR; 以上条件最难判断的是最后一个,我首先用dfs得到交点,然后在做判断。下面具体说明: 1、sum[maxn][maxn][5];//用数组记录当前格子的位置和4个方向的最长长度:
这样每个连续的最长长度就可以求出来了!//0 行 1 列 2 左斜 3 右斜 2、 struct position{ int x , y , dir; position(int a = 0 , int b = 0 , int c = 0){ x = a , y = b , dir = c; } };//用结构体记录连续长度超过m是的点和它的方向; 比如: 6 3 X..... X....O XXO... X.XOO. X..... ...OO. 我就记录了(2,0)(3,0)(4,0)(3,2)这4个点和来自的方向, 3、 vis[maxn][maxn]数组在调用dfs()找交点的时候用,初始为0,记录的是当前这个格子有多少条路经过,每次从2中的记录的点 为入口往前递归,最后如果发现有一个点经过路径的条数==2中记录的点的个数,那么这个点就是交点,如果没有发现这个点, 说明当前这个图是ERROR。这个点记为(centerX , centerY)。 如果有路径在这个点的前半段或后半段(不包括交点) >= m那么这个图是错误的。如果是前半段>=m,用刚才的dfs()找交点 是找不到的,所以很巧妙地避开了前半段的情况,不信在纸上画画写写就知道为什么了!现在只要考虑后半段。后半段只要有2 中的点到交点的长度(不包括交点)>=m,那么就是错误的,这个很好判断吧~
特别注意:
1 1
X
X WINS 完毕!
#include <iostream> #include <cstdio> #include <string> #include <map> #include <vector> #include <cmath> using namespace std; struct position{ int x , y , dir; position(int a = 0 , int b = 0 , int c = 0){ x = a , y = b , dir = c; } }; vector<position> X_p , O_p; const int maxn = 1010; const int dr[4] = {0 , 1 , 1 , 1}; const int dl[4] = {1 , 0 , -1 ,1}; string mp[maxn]; map<char , int> total; int X_sum , O_sum , sum[maxn][maxn][5] , n , m , vis[maxn][maxn] , centerX , centerY; bool ERROR; //0 行 1 列 2 左斜 3 右斜 void initial(){ for(int i = 0; i < maxn; i++){ for(int j = 0; j < maxn; j++){ for(int k = 0; k < 5; k++){ sum[i][j][k] = 0; } vis[i][j] = 0; } mp[i].clear(); } X_sum = 0; O_sum = 0; total['X'] = 0; total['O'] = 0; ERROR = false; centerX = 0; centerY = 0; X_p.clear(); O_p.clear(); } void readcase(){ scanf("%d%d" , &n, &m); for(int i = 0; i < n; i++){ cin >> mp[i]; } } void computing(){ for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(mp[i][j] == 'X'){ total['X']++; for(int k = 0; k < 4; k++){ sum[i][j][k]++; if(m <= sum[i][j][k]){ X_sum = 1; X_p.push_back(position(i , j , k)); } if(sum[i][j][k] >= 2*m){ ERROR = true; return; } int r = i+dr[k] , c = j+dl[k]; if(r >= 0 && r < n && c >= 0 && c < n && mp[r][c] == 'X'){ sum[r][c][k] = max(sum[r][c][k] , sum[i][j][k]); } } } if(mp[i][j] == 'O'){ total['O']++; for(int k = 0; k < 4; k++){ sum[i][j][k]++; if(m <= sum[i][j][k]){ O_sum = 1; O_p.push_back(position(i , j , k)); } if(sum[i][j][k] >= 2*m){ ERROR = true; return; } int r = i+dr[k] , c = j+dl[k]; if(r >= 0 && r < n && c >= 0 && c < n && mp[r][c] == 'O'){ sum[r][c][k] = max(sum[r][c][k] , sum[i][j][k]); } } } } } } bool dfs(int i , int j , int k , int psize , char player){ vis[i][j]++; if(vis[i][j] == psize){ centerX = i; centerY = j; return true; } int r = i-dr[k] , c = j-dl[k]; if(r >= 0 && r < n && c >= 0 && c < n && mp[r][c] == player){ if(dfs(r , c , k , psize , player)) return true; } return false; } void out(){ if(ERROR || total['X'] < total['O']){ printf("ERROR\n"); return; } if(total['X']+total['O'] == n*n){ if(total['X'] == total['O'] || total['X']-total['O'] == 1){ if(n == 1) printf("X WINS\n"); else printf("DRAW\n"); } else printf("ERROR\n"); return; } if(total['X']-total['O'] < -1 || total['X']-total['O'] > 1){ printf("ERROR\n"); return; } if(X_sum && O_sum){ printf("ERROR\n"); return; } if(X_sum){ if(total['X'] - total['O'] != 1){ printf("ERROR\n"); return; } for(int i = 0; i < X_p.size(); i++){ if(dfs(X_p[i].x , X_p[i].y , X_p[i].dir , X_p.size() , 'X')){ for(int j = 0; j < X_p.size(); j++){ if(abs(X_p[j].x-centerX)+1 > m || abs(X_p[j].y-centerY)+1 > m){ printf("ERROR\n"); return; } } printf("X WINS\n"); return; } } printf("ERROR\n"); return; } if(O_sum){ if(total['X'] != total['O']){ printf("ERROR\n"); return; } for(int i = 0; i < O_p.size(); i++){ if(dfs(O_p[i].x , O_p[i].y , O_p[i].dir , O_p.size() , 'O')){ for(int j = 0; j < O_p.size(); j++){ if(abs(O_p[j].x-centerX)+1 > m || abs(O_p[j].y-centerY)+1 > m){ printf("ERROR\n"); return; } } printf("O WINS\n"); return; } } printf("ERROR\n"); return; } printf("IN PROGRESS\n"); } int main(){ int t; scanf("%d" , &t); while(t--){ initial(); readcase(); computing(); out(); } return 0; }