山再高,往上爬,总能登顶;
路再长,走下去,定能到达。
自习课 题目描述
自习课就是划水课。
你和同桌在玩井字棋,你先手。突然老师进来了。
给定一个局面,问它是否有可能下的出来。
若有可能,求出是否有赢家,若有,输出赢家。
否则,输出是否平局,或者下一步是谁的回合。
输入
有多组数据,第一行给出数据组数 T。
每组数据有 3 行,每行 3 个字符。
若字符为”X”,表示这里你下过,若字符为”O”,表示这里同桌下过。
若字符为”.”,表示这里没有人下过。
输出
每个数据输出一行。
若不可能下的出来,输出Illegal Situation
若你赢了,输出X wins,若同桌赢了,输出O wins
若已经下完了,且平局,输出Draw
若下一步是你的回合,输出X's turn
若下一步是同桌的回合,输出O's turn
Sample Input
5
...
XX.
..O
XOX
XXO
OXO
.O.
XO.
.O.
XOX
OX.
X.O
XXX
OOO
...
Sample Output
O's turn
Draw
Illegal Situation
X wins
Illegal Situation
Hint
对于前 60% 的数据,不存在三个”X”或”O”连成一线的情况;
对于 100% 的数据,T≤100。
思路分析 这题考察的就是模拟的能力。打模拟的要诀就是思维缜密+沉住气
模拟的代码都会写,但是一写就wa,这就巨难受。本来这个我认为还OK的代码能过的,就是在比赛场上浮躁了,自己又推翻重写。
下面就详细分析一下我的思路过程。
这题不难,就是问你现在的井字棋走到这个地步了,让你判断以下几个复合什么情况
X先手
0.不可能出现这个情况
1.X该走了
2.O该走了
3.X 已经赢了
4.O 已经赢了
5.平局(没有胜负,都符合规则,已经X+O=9了)
仔细想想,如果当前没有可以连成线的方案,你完全可以根据棋子的数量来判断合法性,如果合法也很容易知道接下来谁走
方案是,先判断有无可成线的棋子
判断X的个数和O的个数
X一定不会比O少
X和O的差距不会大于1
如果满足这个条件OK,那么这就是没有成线且合理
如果X=O那么就说明该X走了
反之O走
如果上面没有给出结果,就说明有三点成线
如果说数量差的离谱,直接一寻找X和O的值的大小就可以了,如上步的方法。可以简单判断是否合法。
如果数量有可能性,且有连成线的,那么就得看看,你现在的Win是否合法(只有一人胜出)
这里就很迷人了。
首先相交的一定是同棋子。(可成的线路相交)而且一个棋子最多为5(X的)
那么一定是可行的。
那么你就寻找一下有没有是平行的可成线。
如果有判不合法
如果没有呢?是不是一定就是成立了呢?
不是的,想要成立的最后一个条件就是,我这个成立情形有没有可能出现。我们在前面只判断了数量差距的不可能性,但是如果我这一步的上一步就不可能实现呢?
比如X有3个O有3个,想X赢的前提是X有2个O有两个这是不可能的,想O赢的前天是X有3个O有两个,这也是不能的。所以,必须得满足这个条件,如果不能则一定不可。
此上已经表达了满足了所有可以成立的条件。
如果依然不能判对,那么这就是错的。
我把生成全部情况的
样例代码奉上
#include
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
int cnt = 0;
int x, y;
char save[20][20];
void id(int t) {
switch (t) {
case 0:x = 0, y = 0;
break;
case 1:x = 0, y = 1;
break;
case 2:x = 0, y = 2;
break;
case 3:x = 1, y = 0;
break;
case 4:x = 1, y = 1;
break;
case 5:x = 1, y = 2;
break;
case 6:x = 2, y = 0;
break;
case 7:x = 2, y = 1;
break;
case 8:x = 2, y = 2;
break;
}
}
void dfs(int t) {
if (t == 9) {
cnt++;
for (int i = 0;
i < 3;
i++)cout << save[i] << endl;
return;
}
id(t);
save[x][y] = '.';
dfs(t + 1);
id(t);
save[x][y] = 'O';
dfs(t + 1);
id(t);
save[x][y] = 'X';
dfs(t + 1);
}
int main() {
freopen("C:\\Users\\hp\\Desktop\\find.txt", "w", stdout);
//自由更改路径
dfs(0);
cout << cnt << endl;
//注意要把cnt的值自己手动放到顶端
fclose(stdout);
}
大家可以吧自己和我的生成数据进行对比,一点点的进行调试。
好吧,接下来上代码
AC时间到
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
【模拟|UPC-自习课】如果有疑问敬请留言。
By-轮月
推荐阅读