CF3C Tic-tac-toe

发布时间 2023-08-27 10:43:19作者: One_JuRuo

AC 后逛了逛题解,发现好像自己的代码比大佬都短很多?

思路

数据范围很小,先暴力求得 X0. 的个数,然后暴力求得连着的三个 X0 的个数。

然后,我们来分类讨论:

  • 非法的情况一定优先判断,只有不非法才可能是其他情况,那么非法的可能有:

    1. \(A\)\(B\) 都能赢。

    2. X 的个数既不是 0 的个数也不是 0 的个数 \(+1\)

    3. 只有 \(A\) 能赢且 X 的数量等于 0 的数量

    4. 只有 \(B\) 能赢且 X 的数量等于 0 的数量。

  • 解释:

    1. 不可能出现两者皆赢的可能。
    2. 棋局中 \(A\) 最多比 \(B\) 多下一子,至少与 \(B\) 一样。
    3. \(A\) 已经赢了,但是 \(B\) 还在继续下棋。
    4. \(B\) 已经赢了,但是 \(A\) 还在继续下棋。
  • 然后是谁赢的情况,这个不用细说

  • 该谁下棋的情况,如果 \(A\) 的棋子数等于 \(B\) 的棋子数,那么该 \(A\) 下,如果 \(A\) 的棋子数等于 \(B\) 的棋子数 \(+1\) 并且有空位置,则该 \(B\) 下。

  • 剩下的就是平局情况了。

总结:情况较多,比较麻烦,但是数据范围很小。

AC code

#include<bits/stdc++.h>
using namespace std;
char ch[4];
int m[4][4],num[3],win[3];
int main()
{
	for(int i=1;i<=3;++i)
	{
		scanf("%s",ch+1);
		for(int j=1;j<=3;++j) m[i][j]=(ch[j]=='X')?1:(ch[j]=='0')?2:0,++num[m[i][j]];//统计每个情况的个数 
	}
	/*统计两人能获胜的个数*/ 
	for(int i=1;i<=3;++i) if(m[i][1]==m[i][2]&&m[i][2]==m[i][3]) ++win[m[i][1]];//同行相同 
	for(int j=1;j<=3;++j) if(m[1][j]==m[2][j]&&m[2][j]==m[3][j]) ++win[m[1][j]];//同列相同 
	if(m[1][1]==m[2][2]&&m[2][2]==m[3][3]) ++win[m[1][1]];//斜角相同 
	if(m[3][1]==m[2][2]&&m[2][2]==m[1][3]) ++win[m[3][1]];//斜角相同
	/*非法情况*/
	if(win[1]&&win[2]) printf("illegal"),exit(0);
	if(num[1]!=num[2]&&num[1]!=num[2]+1) printf("illegal"),exit(0);
	if(win[2]&&num[1]==num[2]+1) printf("illegal"),exit(0);
	if(win[1]&&num[1]==num[2]) printf("illegal"),exit(0);
	/*某人赢的情况*/
	if(win[1]) printf("the first player won"),exit(0);
	if(win[2]) printf("the second player won"),exit(0);
	/*该某人下棋的情况*/
	if(num[1]==num[2]) printf("first"),exit(0);
	if(num[1]==num[2]+1&&num[0])printf("second"),exit(0);
	/*平局情况*/
	printf("draw");
	return 0;
}