【题目描述】
五子棋是一个简单的双人游戏。
小希最近在思索一种更好玩的五子棋。她希望胜利不再是谁先五子连珠谁赢,而变成谁落子后,该子与之前的子五子连珠的次数更多才能胜利。
但是如果是在普通的棋盘上,这个游戏又显得不是很有趣,所以她将棋盘扩大至N*N,因为棋盘过大,没有一个程序能将其展示出来,所以如何落子只能凭借记忆。
她希望你能写一个程序,判断每步落子与之前的同色棋子是否能形成五子连珠。
五子连珠是指是横着竖着或者斜着的八个方向存在连续的颜色相同的至少五个子。
注意:这个版本的五子棋仍然是双人游戏,先手执黑,后手执白。同色才是五子棋。
【输入描述】
第一行一个正整数N,M,表示棋盘大小和落子次数。
随后M行,每行两个整数 xi,yi,表示落子位置。
N,M≤300,000
1≤xi,yi≤N数据保证同一个子的位置不会多次落子。
【输出描述】
对于每一个子,一行,如果该步落下后,该子和其他子能形成五子连珠,输出一个大写的'Y',否则输出一个大写的'N'。
【样例】
示例1
输入
6 12
1 1
6 1
2 2
5 2
3 3
4 3
4 4
3 4
5 5
2 5
6 6
1 6
输出
N
N
N
N
N
N
N
N
Y
Y
Y
Y
思路:首先使用 map 来存放棋子的坐标与颜色,然后进行搜索,只需要棋子计算其他 4 个方向(双向)连续的棋子数,可以进行剪枝优化,即当该棋子某一方向的棋子数达到 4 个,就可以停止
【源代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-6
#define INF 0x3f3f3f3f
#define N 300001
#define LL long long
const int MOD=1e9+7;
using namespace std;
int n,m;
map<int,bool> chesspiece[N];//1为黑色,0为白色
int dx[]={1,1,0,-1,-1,-1,0,1};
int dy[]={0,1,1,1,0,-1,-1,-1};
bool inBound(int x,int y) {//棋盘边界判断
return x<=n && x>=1 && y<=n && y>=1;
}
int calculate(int x,int y,int k){
int sum=1;//棋子总数
while(sum<=5){
int nx=x+dx[k]*sum;
int ny=y+dy[k]*sum;
if(!inBound(x,y) || !chesspiece[nx].count(ny) || chesspiece[x][y]!=chesspiece[nx][ny])
return sum-1;
sum++;
}
return sum;
}
bool judge(int x,int y,bool color){
chesspiece[x][y]=color;
for(int i=0;i<4;i++){
int plus=calculate(x,y,i);//正方向
int minus=calculate(x,y,i+4);//反方向
if(plus+minus+1>=5)//总数大于5
return true;
}
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
if(judge(x,y,i%2))
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
return 0;
}