题目描述
uim最近在研究一种游戏,叫做“yyy棋”。
这种游戏的规则很简单,就是有一个A*B的棋盘和黑白两色的棋子,两个人轮流在下在格子里面。你可以下黑棋或者白棋,中途可以更换颜色,可以下在任何你喜欢的地方,但是要符合以下条件:
1、这个位置不能已经被别的棋子占用。
2、你准备下的地方,上下左右一格范围中不能有和你准备下的颜色一样的棋子。
3、第一个下的人必须出黑子。
当谁没有地方可以放子,谁就输了。
uim把你拉了出来,希望你好好地陪他玩。
由于你很忙不太情愿,uim就让步了,允许你选择先手或者后手。
你突然灵光一现,想到了你小学奥数做到的一个问题:两个人坐在一张桌子的两边,轮流往桌子上放硬币,硬币不能重叠,谁放不下谁就输了。感觉有点类似,所以,你打算借鉴这个办法。
你知道,通过某种策略,你一定是100%赢的。
既然如此,就让uim输个痛快吧。
输入输出格式
输入格式:
第一行,A,B,两个整数,表示棋盘大小
接下来若干行,为uim依次下的顺序,x_i,y_i,c_i,分别表示位置和颜色,颜色1为黑,0为白。位置均1<=x_i<=A 1<=y_i<=B。
入过uim发现没地方可走,就可能会耍赖,将棋子下在了不合法的地方。遇到这种情况,你也要指出。当然uim也有可能知道自己输了后就不下了。不存在游戏胜负还没定uim就投降的情况。
输出格式:
第一行,选择先手还是后手,先手请输出“First”,后手输出“Second”。
接下来几行,如果你是第一个下子的,请输出你的第一步下法。然后对uim的下的每一个子做出回应。输出x_i y_i c_i,意思和上面相同。你必须输出必胜的下法,否则你将WA这个点。如过多个下法都是必胜点,请输出个能够尽早结束游戏的下法。
在你下完这个子之前,请假装你不知道uim的下一步走法。
如果uim耍赖,那么这一行输出“Buwanle”并结束程序,多余的输入就不管它了。
输入输出样例
输入样例#1:
2 2
1 2 1
1 1 1
输出样例#1:
Second
2 1 0
Buwanle
说明
40%数据,2<=A,B<=3
100%数据,2<=A,B<=9
然而作为月赛的第一题,自然是简单的。因为标程的核心代码只有6行。并不需要使用什么复杂算法就可以得到答案。
//以上内容全是题目里面的,包括然而那一句
然而题目真的很简单……虽然是看了题解才发现的。但也是很简单的。关键有一点没加上去:求最短的获胜方法。话说做题时一直有一点没想到,然后月赛结束后看到题目变化了!!!没错,就是想到了小学奥数……然而并没有学过。事实上,就是对称着做的。取对方棋子的对称点,然后就是自己的位置。如果长乘宽等于奇数,那么就先走中心,而且步步颜色相同。否则相反。
然后是代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[11][11];
int p;
inline int wo(int z){
return 1-((z+p)&1); //这是一个神奇的用位运算求颜色的方法。以样例为例。p为偶数,颜色为奇数,加起来为奇数。&1就是1,然后用一减,就是0
}
int main(){
int n,m;
memset(f,-1,sizeof(f));
scanf("%d%d",&n,&m);
p=m&n&1; //这就是为什么p为奇数。只有全是奇数才是奇数
if(p){
cout<<"First"<<endl;
printf("%d %d 1\n",(n+1)>>1,(m+1)>>1);
}
else
cout<<"Second"<<endl;
int x,y,z;
while(scanf("%d%d%d",&x,&y,&z)==3){ //不定项输入的基本方法
if(f[x-1][y]!=z&&f[x+1][y]!=z&&f[x][y+1]!=z&&f[x][y-1]!=z) //判断其实可以写循环的
f[n-x+1][m-y+1]=wo(z); //我方位置
else {
printf("Buwanle");
return 0;
}
f[x][y]=z; //对方位置
printf("%d %d %d\n",n-x+1,m-y+1,f[n-x+1][m-y+1]);
}
}
我觉得很详细了