AC 后逛了逛题解,发现好像自己的代码比大佬都短很多?
思路
数据范围很小,先暴力求得 X
,0
,.
的个数,然后暴力求得连着的三个 X
,0
的个数。
然后,我们来分类讨论:
-
非法的情况一定优先判断,只有不非法才可能是其他情况,那么非法的可能有:
-
\(A\) 和 \(B\) 都能赢。
-
X
的个数既不是0
的个数也不是0
的个数 \(+1\)。 -
只有 \(A\) 能赢且
X
的数量等于0
的数量 -
只有 \(B\) 能赢且
X
的数量等于0
的数量。
-
-
解释:
- 不可能出现两者皆赢的可能。
- 棋局中 \(A\) 最多比 \(B\) 多下一子,至少与 \(B\) 一样。
- \(A\) 已经赢了,但是 \(B\) 还在继续下棋。
- \(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;
}
标签:int,等于,个数,下棋,棋子,tac,情况,CF3C,toe
From: https://www.cnblogs.com/One-JuRuo/p/17659964.html