(2015年郑州轻工业学院ACM校赛题)H 五子棋
我们最后选题策略失败,选到五子棋这题,没想到这题非常麻烦,最后也没做出来!
比赛结束后发了题解再做才做出来! 不得不说 这题真的很麻烦
一个需要比较细致分类讨论的题目。判定棋盘是否合法应考虑如下几种情况:
• 黑先手,因此白子不可能多于黑子,且两种石子数量之差不超过 1;
• 如果黑胜,当前黑子比白子多 1;
• 如果白胜,当前黑白石子数量相等;
• 两方不能同时胜利,即不能出现两方同时有五子相连的情况;
将上述情况判定清楚后,如果没有一方有五子相连则输出 other,否则对于胜的一方,枚举它最后
一步放的是哪个棋子。如果存在这样一个棋子,将它拿走之后局面上就没有五子连珠了,那么我们就可
以到达这个局面(证明略),那么就输出相应的棋子颜色;如果不存在的话(例如棋盘上有 10 个连续的
黑子)则说明局面非法,直接输出 fault 即可。
#include<stdio.h> #include<iostream> #include<stack> #include<queue> #include<math.h> #include<stdlib.h> #include<cstring> #include<algorithm> using namespace std; #define Max(a,b) (a>b?a:b) #define Min(a,b) (a<b?a:b) #define INF 0xfffffff #define maxn 110 #define WHITE 1 #define BLACK 2 #define FAULT 3 #define OTHER 4 int n, m, num; char maps[maxn][maxn]; int dir[4][2] = { {-1,-1},{-1,0},{-1,1},{0,-1} }; void Search(int x,int y,char ch,int k) { num ++; int nx = x + dir[k][0]; int ny = y + dir[k][1]; if(nx >= 0 && nx < n && ny >= 0 && ny < m && maps[nx][ny] == ch ) Search(nx, ny, ch, k); } int MaxNum(char ch) { int ans = 0; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(maps[i][j] == ch) { for(int k=0; k<4; k++) { num = 0; Search(i,j,ch,k); ans = max(ans,num); } } } } return ans; } bool Fault(char ch) { int i, j, k, p, nx, ny; for(i=0; i<n; i++) { for(j=0; j<m; j++) { if( maps[i][j] == ch ) { for(k=0; k<4; k++) { num = 0; Search(i,j,ch,k); if(num >= 5) { for(p=0; p<5; p++) { nx = i + dir[k][0] * p; ny = j + dir[k][1] * p; maps[nx][ny] = '.'; } if(MaxNum(ch) >= 5) return true; for(p=0; p<5; p++) { nx = i + dir[k][0] * p; ny = j + dir[k][1] * p; maps[nx][ny] = ch; } } } } } } return false; } int Slove() { int White = 0, Black = 0; int MaxWhite = 0, MaxBlack = 0; int i, j; for(i=0; i<n; i++) { for(j=0; j<m; j++) { if(maps[i][j] == '1') White ++; if(maps[i][j] == '2') Black ++; } } MaxWhite = MaxNum('1'); MaxBlack = MaxNum('2'); if(MaxWhite > 9 || MaxBlack > 9 || Black-White >= 2 || Black < White ) return FAULT; if(Fault('1')||Fault('2') || (MaxWhite >= 5 && MaxBlack >= 5) || (MaxWhite >= 5 && Black != White)|| (MaxBlack >=5 && Black-1 != White)) return FAULT; if(MaxWhite >= 5 && Black == White) return WHITE; if(MaxBlack >=5 && Black-1 == White) return BLACK; return OTHER; } int main() { int T, i, ans; cin >> T; while(T--) { cin >> n >> m; for(i=0; i<n; i++) cin >> maps[i]; ans = Slove(); if(ans == WHITE) printf("white\n"); else if(ans == BLACK) printf("black\n"); else if(ans == OTHER) printf("other\n"); else printf("fault\n"); } return 0; }