某考试T1 game

题目背景

题目描述

Alice 和 Bob 在一个圆环上玩游戏。圆环上有 n 个位置,按照顺时针顺序 依次标号为 1 到 n。Alice 和 Bob 分别有一个数字集合,集合中都是在 [1, n−1] 内的正整数。游戏开始时会有一个棋子摆在圆环上的某个位置,然后两人轮流 行动。轮到某个人的回合时,他可以从他的集合中选出某个数 x,然后把棋子 沿顺时针方向移动 x 个位置。如果某个人把棋子移动到了 1 号位置,那么他就 获胜了。两个人都会以最优策略行动。 你需要对不同先后手顺序以及棋子初始位置的每种情况,求出谁能获胜, 或者说游戏永远不会结束。

输入输出格式

输入格式:

 

第一行为一个正整数 n。 第二行的第一个正整数 k1 表示 Alice 的集合的大小,接下来的 k1 个正整 数表示 Alice 的集合中的数(保证这些数不会重复)。 第三行的第一个正整数 k2 表示 Bob 的集合的大小,接下来的 k2 个正整 数表示 Bob 的集合中的数(保证这些数不会重复)。

 

输出格式:

 

第一行输出 n − 1 个词,第 i 个词表示 Alice 先手且棋子初始在位置 i + 1 的答案。如果 Alice 必胜输出”Win”,必败输出”Lose”,游戏不会结束输 出”Loop”。 第二行输出 n−1 个词,第 i 个词表示 Bob 先手且棋子初始在位置 i+ 1 的 答案。如果 Bob 必胜输出”Win”,必败输出”Lose”,游戏不会结束输出”Loop”。

 

输入输出样例

输入样例#1: 
5
3 3 1 2
2 2 3
输出样例#1: 
Loop Win Win Win
Lose Win Win Loop

说明

对于 30% 的数据,保证 2 ≤ n ≤ 5。 对于 60% 的数据,保证 2 ≤ n ≤ 300。 对于 100% 的数据,保证 2 ≤ n ≤ 7000, 1 ≤ k1, k2 ≤ n − 1。

 

就是一个最简单的博弈问题,图都不用建一遍dfs就行了。。。

然而我考试的时候忘了标记已经计算过的节点然后才50。。。。。我好菜啊ww

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
#define maxn 7005
using namespace std;
int n,s,t,a[maxn],b[maxn];
int win[maxn*2];
int cnt[maxn*2];
bool vis[maxn*2];

inline int add(int x,int y){
	x+=y;
	if(x>=n) return x-n;
	else return x;
}

inline void bfs(){
	queue<int> q;
	int x,to;
	q.push(0),q.push(n);
	win[0]=win[n]=-1;
	
	while(!q.empty()){
		x=q.front(),q.pop();
		vis[x]=1;
		
		if(x<n){
			for(int i=1;i<=t;i++){
				to=add(x,n-b[i])+n;
				if(vis[to]) continue;
				
				if(win[x]==-1) win[to]=1,q.push(to);
				else if(win[x]==1&&(++cnt[to])==t) win[to]=-1,q.push(to);
			}
		}
		else{
			for(int i=1;i<=s;i++){
				to=add(x,-a[i]);
				if(vis[to]) continue;
				
				if(win[x]==-1) win[to]=1,q.push(to);
				else if(win[x]==1&&(++cnt[to])==s) win[to]=-1,q.push(to);
			}			
		}
	}
}

int main(){
	scanf("%d",&n);
	scanf("%d",&s);
	for(int i=1;i<=s;i++) scanf("%d",a+i);
	scanf("%d",&t);
	for(int i=1;i<=t;i++) scanf("%d",b+i);
	
	bfs();
	
	for(int i=1;i<n;i++){
		if(!win[i]) printf("Loop ");
		else if(win[i]==1) printf("Win ");
		else printf("Lose ");
	}
	puts("");
	for(int i=1;i<n;i++){
		if(!win[i+n]) printf("Loop ");
		else if(win[i+n]==1) printf("Win ");
		else printf("Lose ");
	}	
	
	return 0;
}

  

posted @ 2018-02-27 19:12  蒟蒻JHY  阅读(428)  评论(0编辑  收藏  举报