1 条题解
-
0
自动搬运
来自洛谷,原作者为

stone_juice石汁
敲稀有滴物种石汁qaq搬运于
2025-08-24 21:31:52,当前版本为作者最后更新于2019-08-11 21:10:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
瞟了一眼题解的做法,感觉都把这道题做麻烦了。
不需要花里胡哨的双重枚举每个点,也不需要什么数组
并且只需要行就可以写完。
那么怎么做到这种操作的 O_O?
思路
首先,注意题目中给了两个信息:
-
、小a每次都先下,并且都是下正中心位置。
-
、在场的棋子数不超过三颗
我不知道是不是有人没注意到这两个信息。这直接决定了思路的繁简 和 代码的长短。
我们来分析一下这两个信息:
-
、小a每次占住正中心位置,毫无疑问这是巨大优势,这时候小a不管下在哪里都可以凑成两颗,而uim则不得不防守。
-
、在场的棋子数不超过三颗,这意味着当时的情况一定未分出胜负(所以写什么判断当时是否出现胜负那是完全不必要的)。
那么,
江南老赌手石汁教你如何下三子棋,保证不输的那种。由于小a每次都会站中间,所以我们直接默认中间是

很明显,在只有一颗棋子时,完全判断不出胜负。
我们可以把这张图看成对称的,那么现在,uim就只有两种选择。
- Ⅰ、走边角
也就是走四个角的位置。这样走无疑是很明智的,因为这么一走,uim就可以控制三条线。

如果uim够聪明,这样走,基本上小a就没戏了。
但是如果小a也够聪明,小a也不会输掉。
为什么这么说?
首先,小a在这种情况下必定会再下一颗棋子。只要它不下的对角线位,那么uim在下一步必须防守。
如图例:

此时,uim挡住了小a的进攻,并且又控制住了一条边。
小a很可怜了,只能走淡蓝色格子来凑成三颗,但很明显,它要走两步才能凑足。肯定不会给他这个机会
但是,也一直处于堵小a旗子的状态,导致他根本没机会凑足三颗,除非小a太傻了。
当然,如果uim智商下线,小a也有可能会赢。所以完全猜不透到底是平了还是谁赢了。
总结:uim第二颗走边角,完全不知道结果。
- Ⅱ、走邻边
这里所指的邻边,就是排除四个边角,相邻的方格。
那么想想,uim走邻边会发生什么。
走邻边,意味着uim这颗棋子只能控制住两条边,如下图。

那么此时,小a只要不走的对边位置,小a就凑成了两连颗。
理所当然地,uim必然会再出一颗棋子去防守,并且又控制住一条边。
但是这完全无济于事,就算如此,小a还是有三条可行线路可以让他连到颗
如图:

其中打 号的,代表着两种可行线路的重叠部位。只要小a落子此处,必然会形成双局面。
uim可以堵,但堵得住一个,堵不住两个啊。所以uim会输。
在小a很菜的情况下,可能会不知道谁胜谁负,但是题面中写了这么一句话:以最佳方案下棋,无论对手怎么下,自己必胜
所以,只要有自己必胜的方案就可以了。刚刚无疑满足了这种情况
- 特殊情况
uim走邻边有一种特殊情况
-O- -O- -X-图丢了就不弄图了
(其实想偷懒QAQ)虽然我们上面提到过,小a不可能会这么下,但是要是数据里有这种情况,就必须特判。
但问题是数据并没涉及到这种情况所以我就没写上去了总结:除特殊情况,uim第二颗走邻边,小a必赢。
在加上落子数不可能超过三颗,也就是uim最多落一颗子。
综合上面所有条件,最后的最后,所有情况化为一句话:
只要uim敢下邻边,那他必输
其他情况则不明输赢
你看,玩这个游戏是不是可以保证不输QAQ,你先手必赢,你后手必不会输。
代码实现
呼,说了这么多,结果结论只有两句话....
我们只需要判断uim是否下邻边就行了对吧?
很简单,直接用一层从跑到,每次输入一个字符
如果为偶数,并且发现输入的是一个,就可以直接判uim负了
如果没有出现上述情况,输出“不知道”即可。
先上一个可读性比较高的代码:
#include<bits/stdc++.h> using namespace std; int ans; char x; bool pd; //pd:判断,用于判断uim是否输了 int main() { for(int i = 1; i <= 9; i ++) { scanf("%c", &x); if(x == 'X' && !(i % 2))pd = true; //此时,uim已经输了 if(x == '-') ans ++; //由于我们还要输出棋子个数,我们则记录空格个数,用9-空格个数就知道棋子个数了 } if(pd == true) cout << "xiaoa will win." << endl << 9 - ans; else cout << "Dont know." << endl << 9 - ans; return 0; }再上我之前说过的8行代码
(并且格式是标准的)
#include<bits/stdc++.h> int ans, x, pd; int main(){ for(int i = 1; ~scanf("%c", &x); i ++) if(x == 'X' && !(i % 2)) pd = true; else if(x == '-') ans ++; std::cout << (pd ? "xiaoa will win." : "Dont know.") << std::endl << 9 - ans; }后记
这篇题解写的耗时有点久了,还要专门去配图A.A,希望大家都能看懂吧
如果有什么不懂得地方可以留言,我有时间必会看的。
看我这么苦的份上,是不是应该.... -
- 1
信息
- ID
- 885
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者