bzoj 2940: [Poi2000]条纹 (Multi-SG游戏)

2940: [Poi2000]条纹

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 83   Solved: 54
[ Submit][ Status][ Discuss]

Description

     条纹游戏是一个双人的游戏。所需要的物品有一个棋盘以及三种颜色的长方形条纹,这三种颜色分别是红色、绿色和蓝色。所有的红色条纹的尺寸是 c*1 ,所有的绿色条纹的尺寸是 z*1 ,所有的蓝色条纹的尺寸是 n*1 ,这里 c,z,n 是正整数。每种颜色的条纹每个游戏者都拥有无限多个。
        一个棋盘是一个尺寸为 p*1 的长方形,由 p 1*1 的方格组成。
        游戏者轮流走,每一步都是由一个游戏者任选一种长方形条纹覆盖到棋盘上,并要求遵循以下规则:
l         条纹不能伸出棋盘之外。
l         不能覆盖在已有的条纹之上(即使部分也不行)。
l         条纹的边缘必须与棋盘方格的边缘相重叠。谁不能再走,谁就输了。
 
先手是指在游戏中第一个走的游戏者。那么是否不管后手怎么走,先手都有必胜策略呢?
任务:
写一个程序:
l         读入条纹的尺寸以及至少一个棋盘的尺寸。
l         对每一个给出的棋盘判断先手是否必胜。
l         将结果输出
 

Input

  第一行包含三个整数 c,z,n(1<=c,z,,n<=1000) ,表示三种条纹的长度,依次为红色,绿色以及蓝色。每两个数之间都用空格隔开。
        文件的第二行包括一个整数 m 1 <= m <= 1000 )表示需要考虑的不同棋盘个数。以下 3 m+2 行每行包括一个整数 p 1<=p<=1000 )。第 i+2 行表示第 i 个棋盘的长度。
 

Output

    应当包含 m 行。只有一个数字应当被写入文件的第 i 行:
l         1 —如果对第 i 个棋盘先手有必胜策略。
l         2 —其它。
 

Sample Input

1 5 1


3
1
5
6


Sample Output


1
1
2

HINT

Source

[ Submit][ Status][ Discuss]

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 2003
using namespace std;
int sg[N],a,b,c,n;
int get(int x)
{
	if (sg[x]!=-1) return sg[x];
	int hash[N]; 
	memset(hash,0,sizeof(hash));
	if (x>=a) 
		for (int i=1;i<=x-a+1;i++) hash[get(i-1)^get(x-i-a+1)]=1;
	if (x>=b)
	    for (int i=1;i<=x-b+1;i++) hash[get(i-1)^get(x-i-b+1)]=1;
	if (x>=c)
	    for (int i=1;i<=x-c+1;i++) hash[get(i-1)^get(x-i-c+1)]=1;
	for (int i=0;i<=x;i++) 
	 if (!hash[i]) {
	 	sg[x]=i;
	 	return sg[x];
	 }
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d%d%d",&a,&b,&c);
	scanf("%d",&n);
	memset(sg,-1,sizeof(sg)); 
	for (int i=0;i<min(a,min(b,c));i++) sg[i]=0;
	for (int i=1;i<=n;i++) {
		int x; scanf("%d",&x);
		get(x);
		//for (int i=1;i<=x;i++) cout<<sg[i]<<" ";
		//cout<<endl;
		if (sg[x]) puts("1");
		else puts("2");
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值