下棋(chess)
下棋
题目描述
给出一个 n行 m列的棋盘,棋盘是立起来的,也就是说上面的棋子受到重力的作用,所有棋子位于该列的最下方(即不在最后一行的棋子下方都有棋子)。
当棋盘上出现 k 子连珠(即横、竖、斜中有连续k 个子颜色相同,类似五子棋的胜利条件)时,游戏结束。
现在给出 t 个操作,每次操作在第 x 列顶端加入一个棋子。若加入该棋子前棋盘上有偶数个棋子则加入的是黑色棋子,否则加入的是白色棋子。
问游戏结束时棋盘上有多少个棋子。
保证落子一定合法,保证游戏一定会结束
解题思路
最直接的想法是模拟每次落子,然后检查是否形成k连珠。
对于每次落子:
- 找到该列当前最顶端的空位
- 放入棋子(颜色根据当前棋子总数决定)
- 从该位置开始,检查四个方向(水平、竖直、主对角线、副对角线)是否存在
k连珠
优化:
因为每次都是从当前点判断,所以不用去寻找全图,只从当前点扩展就好了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,k,t,st[N][N];
int a[N],flag;
int cnt;
int f(int x,int y,int nx,int ny){
int ans=1;
for(int i=1;i<=k;i++){
if(x+i*nx<=0||x+i*nx>n||y+i*ny<=0||y+i*ny>n||st[x+i*nx][y+i*ny]!=st[x][y]) break;
ans++;
}
for(int i=1;i<=k;i++){
if(x-i*nx<=0||x-i*nx>n||y-i*ny<=0||y-i*ny>n||st[x-i*nx][y-i*ny]!=st[x][y]) break;
ans++;
}
return ans;
}
bool check(int x,int y){
if(f(x,y,1,0)>=k||f(x,y,1,1)>=k||f(x,y,1,-1)>=k||f(x,y,0,1)>=k) return true;
else return false;
}
int main(){
cin >> n >> m >> k >> t;
while(t--){
++cnt;
int x;
cin >> x;
if(flag) continue;
st[++a[x]][x]=cnt%2+1;
if(check(a[x],x)){
cout << cnt;
flag=1;
}
}
}

浙公网安备 33010602011771号