# ZOJ 1039 Number Game 记忆化搜索+二进制状态压缩

Number Game

Time Limit: 10 Seconds      Memory Limit: 32768 KB

Background

Christiane and Matthias are playing a new game, the Number Game. The rules of the Number Game are:

Christian and Matthias take turns in choosing integer numbers greater than or equal to 2. The following rules restrict the set of numbers which may be chosen:

R1 A number which has already been chosen by one of the players or a multiple of such a number cannot be chosen. (A number z is a multiple of a number y if z can be written as y * x and x is a positive integer.)

R2 A sum of two such multiples cannot be chosen either.

R3 For simplicity, a number which is greater than 20 cannot be chosen either. This enables a lot more NPCs (Non-Personal-Computers) to play this game.

The player who cannot choose any number anymore looses the Number Game.

Here is an example: Matthias starts by choosing 4. Then Christiane is not allowed to choose 4, 8, 12, etc. Let us assume her move is 3. Now, the numbers 3, 6, 9, etc. are excluded, too; furthermore, numbers like: 7 = 3 + 4, 10 = 2 * 3 + 4, 11 = 3 + 2 * 4, 13 = 3 * 3 + 4, . . . are not available. So, in fact, the only numbers left are 2 and 5. Matthias now says 2. Since 5 = 2 + 3 is now forbidden, too, he wins because there is no number for Christiane's move left.

Your task is to write a program which will help to play the Number Game. In general, i.e., without rule R3, this game may go on forever. However, with rule R3, it is possible to write a program that finds a strategy to win the game.

Problem

Given a game situation (a list of numbers which are not yet forbidden), your program should output all winning moves. A winning move is a move by which the player whose turn it is can force a win no matter what the other player will do. Now we define these terms more formally:

A loosing position is a position in which either

1. all numbers are forbidden, or

2. no winning move exists.

A winning position is a position in which a winning move exists.

A winning move is a move after which the position is a loosing position.

Input

The first line contains the number of scenarios.

The input for each scenario describes a game position. It begins with a line containing the number a, 0 <= a < 20 of numbers which are still available. Next follows a single line with the a numbers still available, separated by single blanks.

You may assume that all game positions in the input could really occur in the Number Game (for example, if 3 is not in the list of numbers available, 6 will not be, either).

Output

The output for each scenario begins with a line containing "Scenario #i:" where i is the number of the scenario starting at 1. In the next line either print "There is no winning move." if this is true for the position of the current scenario, or "The winning moves are: w1 w2 . . . wk." where the wi are all the winning moves, in ascending order, separated by single blanks. The output for each scenario should be followed by a blank line.

Sample Input

2
1
2
2
2 3

Sample Output

Scenario #1:
The winning moves are: 2.

Scenario #2:
There is no winning move.

dp[i]表示对于i这个数表示的状态集合，起始时都初始化为0.。dp[i]=1时，i表示一个状态集合。对于可选的某个数，对他进行遍历，如果选了这个数以后，他所能到达的所有状态都是必输状态，即选了这个数，对手没有数可选了或者选神马都是输，那就把这个数标记为必胜状态。

#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;

int n;
int a;
int MAX=1<<19;

int win[(1<<19)+10];

{
for(int i=x;i<=20;i+=x)//删除倍数
{
ret&=~(1<<(i-2));
}

for(int i=2;i<=20;i++)
{
if( (ret&(1<<(i-2))))//枚举还存在的数
{
for(int j=i-x;j>=2;j-=x)//找是否存在两个非法数和也非法的情况
{
if(!(ret&(1<<(j-2))))
{
ret&=~(1<<(i-2));
break;
}
}
}
}

return ret;
}

{
return 0;
return 1;

for(int i=2;i<=20;i++)
{
{
if(!dfs(tmp))//如果后面所有都是必输，那么这一步就是必赢
{
return 1;
}
}
}

return 0;
}

int main()
{
int T;

scanf("%d",&T);
{
for(int ca=1;ca<=T;ca++)
{
memset(win,-1,sizeof win);

for(int i=0;i<19;i++)
win[1<<i]=1;

scanf("%d",&n);

for(int i=0;i<n;i++)
{
scanf("%d",&a);
}

printf("Scenario #%d:\n",ca);

{
printf("There is no winning move.\n\n");
}
else
{
printf("The winning moves are:");
for(int i=2;i<=20;i++)
{
{
if(!dfs(tmp))//如果之后对方是必输局，则这是必胜选择
cout<<" "<<i;
}
}

puts(".\n");
}

}

}
return 0;
}


• 本文已收录于以下专栏：

## zoj1039 Number Game 博弈+DP+状态压缩

Number Game Time Limit: 10 Seconds      Memory Limit: 32768 KB Background Christiane and...

## CF-63E - Sweets Game(记忆化搜索dp+状态压缩)

E - Sweets Game Time Limit:3000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Su...

## poj 1143 Number Game 博弈 记忆化状态压缩搜索

poj 1143 Number Game http://poj.org/problem?id=1143 第一道博弈题，纠结了好久好久好久…… 题意：给定2到20的数，当选择一个数后，次数的倍数不...

## hdu 4628 Pieces（状态压缩＋记忆化搜索）

Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total...

## uva1508-Equipment 状态压缩 记忆化搜索

ICPC 2011 Asia Regional Daejeon Problem D : Equipment The 3 6 th Annual ACM Internatio...
• corncsd
• 2014年02月01日 16:42
• 391

## vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签：[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n。 游戏规则是这样的：...

## UVa 10118 Free Candies （记忆化搜索+状态压缩）

举报原因： 您举报文章：ZOJ 1039 Number Game 记忆化搜索+二进制状态压缩 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)