sg变形——一堆变多堆

原题连接 http://www.acm.cs.ecnu.edu.cn/problem.php?problemid=1328

Stripes

Time Limit:1000MS Memory Limit:30000KB
Total Submit:23 Accepted:11

Description
Stripes is a two player game. Necessary requisites are a board and rectangular stripes in three colours: red, green and blue. All the red stripes have dimensions c x 1, green - z x 1, and blue - n x 1, where c, z and n are integers. Players have at their disposal an unlimited pool of stripes of each colour.
A game board is a rectangle of dimensions p x 1 and consists of p fields of size 1 x 1.
Players make their moves by turns. Move consists of laying a stripe of any colour on the board. There are the following rules in force:
A stripe cannot stick out of the board,
The covering (even partially) the earlier laid stripes is forbidden.
The ends of a stripe have to adhere to the edges of the fields on the board. The player, who is not able to perform his move in accordance to the game rules first, loses.
The first player is this one, who makes the first move in the game. It is said, that the first player has a winning strategy, if independently of the moves of the second player he can always win.
Task
Write a program, which:
1.reads sizes of stripes and of at least one board
2.for each board determines, whether the first player has a winning strategy,
3.writes the results.

Input
The first line of the input consists of three integers c, z and n, 1 <= c, z, n <= 1000, equal to the lengths of stripes, adequately: red, green and blue ones. Numbers in the line are separated by single spaces.
The second line of the file PAS.IN consists of one number m, 1 <= m <= 1000, which is equal to the number of different boards to consider. Lines from the 3-rd to the (m+2)-th consists of one number p, 1 <= p < 1000. Number in the (i+2)-th line is the length of the i-th board.

Output
The output should contain m lines. Only one number should be written in the i-th line of the file:
1 - if the first player has a winning strategy on the i-th board
2 - otherwise.

Sample Input
1 5 1
3
1
5
6

Sample Output
1
1
2

Source

POI 2000 I Stage

张一飞同学的论文里的一道题。

一堆石子,你取r,g,b个,但是必须连续,最后谁不能取了,谁就失败了。

与之前的nim不一样,这个游戏是随着过程,石子堆不断增加的。但是我们判断一个状态是不是必输态,本质上来说,仍然要一步一步的找。就是看这个状态的子状态是不是必输,或者必胜的。这个是组合游戏的不变的出发点。

考虑一个状态的子状态:

就两种,一个是从边上取,这样子状态就一堆;

或者从中间取,子状态变为两堆了。

我们仍然用sg函数的思想。但是请注意,在单一游戏里,在构造sg时,用了小规模的sg函数的和的形式。这就是这道题的价值。子状态变为2堆时,我们要求sg和来判断是什么态。

#include <cstdio>
#include <iostream>
using namespace std;
int board[1000];
int color[3];
int m;
int dp[1000];
bool hash[1000];
int t;
void sg(){
  for(int i=0; i<=1000; ++i){
  memset(hash,0,sizeof(hash));
  for(int j=0; j<3; ++j)
  for(int k=color[j]; k<=i; ++k){
  t=dp[k-color[j]]^dp[i-k];
  hash[t]=1;
}
   for(int k=0; k<1000; ++k)
     if(hash[k]==0)
       { dp[i]=k;break;}
}
}
int main(){
while(~scanf("%d%d%d",&color[0],&color[1],&color[2])){
memset(dp,0,sizeof(dp));
sg();
scanf("%d",&m);
for(int i=0; i<m; ++i){
  scanf("%d",board+i);
}
for(int i=0; i<m; ++i)
  if(dp[board[i]]==0) printf("2/n");
  else printf("1/n");
}
}

你可能感兴趣的:(sg变形——一堆变多堆)