下棋(chess)

下棋

题目描述

给出一个 nm列的棋盘,棋盘是立起来的,也就是说上面的棋子受到重力的作用,所有棋子位于该列的最下方(即不在最后一行的棋子下方都有棋子)。

当棋盘上出现 k 子连珠(即横、竖、斜中有连续k 个子颜色相同,类似五子棋的胜利条件)时,游戏结束。

现在给出 t 个操作,每次操作在第 x 列顶端加入一个棋子。若加入该棋子前棋盘上有偶数个棋子则加入的是黑色棋子,否则加入的是白色棋子。

问游戏结束时棋盘上有多少个棋子。

保证落子一定合法,保证游戏一定会结束

解题思路

最直接的想法是模拟每次落子,然后检查是否形成k连珠。

对于每次落子:

  1. 找到该列当前最顶端的空位
  2. 放入棋子(颜色根据当前棋子总数决定)
  3. 从该位置开始,检查四个方向(水平、竖直、主对角线、副对角线)是否存在 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;
		}
	}
}
posted @ 2026-07-10 10:08  zhangyirui  阅读(7)  评论(0)    收藏  举报