【ICPC】2022合肥热身赛 B. Chess | 博弈论

119 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

【ICPC】2022合肥热身赛 B. Chess | 博弈论

题目

image.png

题目大意

Alice 和 Bob 玩游戏。

有一个 n×nn\times n 的棋盘摆满了棋子,输入描述了每个棋子是黑色还是白色。每次操作中:

  • Alice 可以选择一个黑色棋子,并把该棋子它右边所有的棋子都取走。
  • Bob 可以选择一个白色棋子,并把该棋子它右边所有的棋子都取走。

请对于给定的棋盘,判断该局游戏属于以下哪一种情况:

  1. Alice 必胜。
  2. Bob 必胜。
  3. 先手必胜。
  4. 后手必胜。

思路

显然每个人操作的最优策略都是:选择每一行最靠右的可以选择的棋子中,可以顺便带走最多对方可以选择的棋子的那一个。

因为数据范围很小,n100n\le 100,我们可以分别让 Alice 和 Bob 作为先手,进行两次游戏,每次暴力模拟双方的选择。得到两次游戏的答案后:

  • 如果不管谁是先手都是 Alice 胜利输出 1。
  • 如果不管谁是先手都是 Bob 胜利输出 2。
  • 两轮游戏均为先手获胜输出 3。
  • 两轮游戏均为先手获胜输出 4。

代码

#include<bits/stdc++.h>
using namespace std;
int a[101][101],n,last[101];
int main() {
	scanf("%d", &n);
	int a1 = 0, b1 = 0, a2 = 0, b2 = 0;
	for( int i = 1; i <= n; i++) {
		string s;cin >> s;
		for( int j = 1; j <= n; j++) {
			if(s[j-1] == 'W') a[i][j] = 1;
		}
	} for( int i = 1; i <= n; i++) last[i] = n;
	int alice = 1, bob = 0;
	for( int ii = 1; ii <= 10000; ii++) {
		pair<int,int>z;
		int now = -1;
		if(alice) {
			for( int i = 1; i <= n; i++) {
			   int cnt0 = 0;
		       for( int j = last[i]; j >= 1; j--) {
				   if(a[i][j] == 1) {
				   	  if(cnt0 > now) {
				   	  	 now = cnt0;
				   	  	 z = {i, j-1};
					   }
					   break;
				   }
				   else cnt0++;
			   }				
			}	
		}
		else {
			for( int i = 1; i <= n; i++) {
			    int cnt0 = 0, cnt1 = 0;
		        for( int j = last[i]; j >= 1; j--) {
			    	if(a[i][j] == 0) {
				   	    if(cnt1 > now) {
				   	  		now = cnt1;
				   	  	 	z = {i, j-1};
					   	}
					   	break;
				   	}
				   	else cnt1++;
				}			
			}
		}
		if(now != -1) {
                        last[z.first] = z.second; alice ^= 1; bob ^= 1;			
		}
                else {
                        if(alice) b1 = 1;
                        else a1 = 1;
                        break;
                }
	}
	for( int i =1; i <= n; i++) last[i] = n;
	bob = 1, alice = 0;
	for( int ii = 1; ii <= 10000; ii++) {
		pair<int,int>z;
		int now = -1;
		if(alice) {
			for( int i = 1; i <= n; i++) {
			   int cnt0 = 0;
		       for( int j = last[i]; j >= 1; j--) {
				   if(a[i][j] == 1) {
				   	  if(cnt0 > now) {
				   	  	 now = cnt0;
				   	  	 z = {i, j-1};
					   }
					   break;
				   }
				   else cnt0++;
			   }				
			}	
		}
		else {
			for( int i = 1; i <= n; i++) {
			    int cnt0 = 0, cnt1 = 0;
		        for( int j = last[i]; j >= 1; j--) {
			    	if(a[i][j] == 0) {
				   	    if(cnt1 > now) {
				   	  		now = cnt1;
				   	  	 	z = {i, j-1};
					   	}
					   	break;
				   	}
				   	else cnt1++;
				}			
			}
		}
		if(now != -1) {
                        last[z.first] = z.second; alice ^= 1; bob ^= 1;			
		}
                else {
                        if(alice) b2 = 1;
                        else  a2 = 1;
                        break;
                }
	}
	if(a1 && a2) printf("1\n");
	else if(b1 && b2) printf("2\n");
	else if(a1 && b1) printf("3\n");
	else printf("4\n");
        return 0;
}