时间限制1.00s 内存限制512.00MB 难易度:普及−
【题目描述】
zyl 和「她」在 n×m 的格子纸上下五子棋。「她」总是先手。
现在你会得知以下信息:
- 格子纸的大小 n,m,代表棋盘共 n 行 m 列。
- n 个仅由字符
~
、*
、$
构成的长度为 m 的字符串(即 n×m 个字符)。对于第 i 个字符串的第 j 个字符,~
表示第 i 行第 j 列的格子是空的,*
表示「她」已经在这一格落下棋子,$
表示 zyl 已经在这一格落下棋子。
类似于五子棋的基本规则,一局棋局由「先手」开始,双方轮流落子。如果有同一行,同一列,或者同一 45° 斜对角线有同一方的连续五个棋子,那这一方便是胜者。
现在,请你以以下方式判断当前的棋局:如果已有一方获胜,请你判断是哪一方获胜。否则,请你判断当前轮到哪一方落子。
【输入格式】
输入共 n + 1 行。
第一行两个整数 n,m,表示格子纸的大小。
接下来 n 行,每行一个长度为 m 的,仅由字符 ~
、 *
、$
组成的字符串,代表棋局的情况。
输出格式
输出共一行一个字符串或一个字符,表示棋局的情况。
- 如果已有一方获胜,输出一个字符串
Pleasing!
或zylwins!
。Pleasing!
表示「她」获胜,zylwins!
表示 zyl 获胜。 - 否则,输出一个字符
W
或Z
。W
表示当前轮到「她」落子,Z
表示轮到 zyl 落子。
【输入输出样例】
输入 #1
5 5 ~~*~$ ***~~ ~$*~~ ~~*~$ $$*$~
输出 #1
Pleasing!
【说明/提示】
样例 1 解释
在第三列有连续的五个 *
,所以「她」获胜了。
数据规模与约定
对于前 40% 的数据,保证没有任何一方获胜。
对于 100% 的数据, 5≤n,m≤30,字符串仅由 ~
、*
、#
组成,而且不会出现任意同一行,同一列或是同一 45° 斜对角线上有连续 6 个或以上连续且相同的 *
或 #
,并且最多只有一条连续的 5 个 *
或 $
。 *
的总数不小于 $
的总数,且至多比 $
的总数大 1。保证输入的字符串至少存在一个字符 ~
。
【算法分析】
对于这道题,判断该谁落子比较简单,只需记录 *
和 $
的数量,如果相等,则说明一个回合恰好结束,应该轮到先手落子。反之,*
的数量比 $
的数量多一,则该轮到后手即 zyl 落子。
至于是否有人胜利,如果写一堆判断语句会和麻烦,我们可以开两个数组 dx 和 dy 分别存储每个方向相邻棋子对应的横、纵坐标的差值。判断胜负时,我们每次将坐标加上这两个差值,看新坐标的棋子是否和原坐标上的棋子一样,重复 4 遍即可。
【参考代码】
#include <bits/stdc++.h>
using namespace std;
int dx[4]={0,1,-1,1};
int dy[4]={1,0,1,1};
char c[35][35];
int n,m,l,r;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>(c[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(c[i][j]=='~') continue;
l+=c[i][j]=='*';
r+=c[i][j]=='$';
for(int k=0;k<4;k++)
{
int x=i,y=j;
bool f=1;
for(int t=1;t<=4;t++)
{
x+=dx[k];
y+=dy[k];
if(x<1||y<1||x>n||y>m)
{
f=0;
break;
}
if(c[x][y]!=c[i][j])
{
f=0;
break;
}
}
if(f==1)
{
if(c[i][j]=='*')
{
cout<<"Pleasing!";
return 0;
}
else{
cout<<"zylwins!";
return 0;
}
}
}
}
if(l==r) cout<<"W";
else cout<<"Z";
return 0;
}