[POJ1143]Number Game

试题描述

Christine and Matt are playing an exciting game they just invented: the Number Game. The rules of this game are as follows. 
The players take turns choosing integers greater than 1. First, Christine chooses a number, then Matt chooses a number, then Christine again, and so on. The following rules restrict how new numbers may be chosen by the two players:

  • A number which has already been selected by Christine or Matt, or a multiple of such a number,cannot be chosen.
  • A sum of such multiples cannot be chosen, either.

If a player cannot choose any new number according to these rules, then that player loses the game. 
Here is an example: Christine starts by choosing 4. This prevents Matt from choosing 4, 8, 12, etc.Let's assume that his 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 also not available. So, in fact, the only numbers left are 2 and 5. Christine now selects 2. Since 5=2+3 is now forbidden, she wins because there is no number left for Matt to choose. 
Your task is to write a program which will help play (and win!) the Number Game. Of course, there might be an infinite number of choices for a player, so it may not be easy to find the best move among these possibilities. But after playing for some time, the number of remaining choices becomes finite, and that is the point where your program can help. Given a game position (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 who is about to move can force a win, no matter what the other player will do afterwards. More formally, a winning move can be defined as follows.

  • A winning move is a move after which the game position is a losing position.
  • A winning position is a position in which a winning move exists. A losing position is a position in which no winning move exists.
  • In particular, the position in which all numbers are forbidden is a losing position. (This makes sense since the player who would have to move in that case loses the game.)

输入

The input consists of several test cases. Each test case is given by exactly one line describing one position. 
Each line will start with a number n (1 <= n <= 20), the number of integers which are still available. The remainder of this line contains the list of these numbers a1;...;an(2 <= ai <= 20). 
The positions described in this way will always be positions which can really occur in the actual Number Game. For example, if 3 is not in the list of allowed numbers, 6 is not in the list, either. 
At the end of the input, there will be a line containing only a zero (instead of n); this line should not be processed.

输出

For each test case, your program should output "Test case #m", where m is the number of the test case (starting with 1). Follow this by either "There's no winning move." if this is true for the position described in the input file, or "The winning moves are: w1 w2 ... wk" where the wi are all winning moves in this position, satisfying wi < wi+1 for 1 <= i < k. After this line, output a blank line.

输入示例


输出示例

Test Case #
The winning moves are: Test Case #
There's no winning move. Test Case #
The winning moves are: 6

数据规模及约定

见“输入

题解

这是一道博弈题,那么肯定是 dp 了。

一看数字这么少,自然想到状压 dp。根据博弈题的惯例,我们要枚举当前状态选举那个数字然后进行转移。

设 f(S) 表示当前剩余数字集合为 S,先手必胜还是必输。那么转移是枚举每个可以取的数字,假设我选择了数字 x,那么对于每一个数字 y,如果 y 没有在集合 S 中出现,则 x + y 这个数字也不能取了;同时注意,如果新产生了一个不能取的数,那么这个数 + x 也是不能取的(类似于对于这个集合 S 又做了一次无限背包);把所有不能取的数从状态 S 中去掉得到新的状态 tS 就可以转移了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 25
#define maxs 1048576 char str[maxn];
char* bin_(int x) {
int l = 0;
while(x) str[l++] = (x & 1) + '0', x >>= 1;
while(l < 19) str[l++] = '0';
str[l] = 0;
return str;
} int f[maxs];
int dp(int S) {
if(!S) return f[S] = 0;
if(f[S] >= 0) return f[S];
for(int i = 0; i < 19; i++) if(S >> i & 1) {
int x = i + 2, tS = S ^ (1 << i);
for(int j = 0; j < 19; j++)
if(j + x < 19 && !(tS >> j & 1) && (tS >> j + x & 1)) tS ^= (1 << j + x);
if(!dp(tS)) return f[S] = 1;
}
return f[S] = 0;
} int cnt, Ans[maxn]; int main() {
int kase = 0;
while(1) {
int n = read();
if(!n) break;
int S = 0;
for(int i = 1; i <= n; i++) S |= (1 << read() - 2);
memset(f, -1, sizeof(f));
printf("Test Case #%d\n", ++kase);
if(dp(S)) {
printf("The winning moves are: ");
cnt = 0;
for(int i = 0; i < 19; i++) if(S >> i & 1) {
int x = i + 2, tS = S ^ (1 << i);
for(int j = 0; j < 19; j++)
if(j + x < 19 && !(tS >> j & 1) && (tS >> j + x & 1)) tS ^= (1 << j + x);
if(!dp(tS)) Ans[++cnt] = x;
}
for(int i = 1; i <= cnt; i++) printf("%d%c", Ans[i], i < cnt ? ' ' : '\n');
putchar('\n');
}
else puts("There\'s no winning move.\n");
} return 0;
}

[POJ1143]Number Game的更多相关文章

  1. Number Game poj1143

    Description Christine and Matt are playing an exciting game they just invented: the Number Game. The ...

  2. JavaScript Math和Number对象

    目录 1. Math 对象:数学对象,提供对数据的数学计算.如:获取绝对值.向上取整等.无构造函数,无法被初始化,只提供静态属性和方法. 2. Number 对象 :Js中提供数字的对象.包含整数.浮 ...

  3. Harmonic Number(调和级数+欧拉常数)

    题意:求f(n)=1/1+1/2+1/3+1/4-1/n   (1 ≤ n ≤ 108).,精确到10-8    (原题在文末) 知识点:      调和级数(即f(n))至今没有一个完全正确的公式, ...

  4. Java 特定规则排序-LeetCode 179 Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  5. Eclipse "Unable to install breakpoint due to missing line number attributes..."

    Eclipse 无法找到 该 断点,原因是编译时,字节码改变了,导致eclipse无法读取对应的行了 1.ANT编译的class Eclipse不认,因为eclipse也会编译class.怎么让它们统 ...

  6. 移除HTML5 input在type="number"时的上下小箭头

    /*移除HTML5 input在type="number"时的上下小箭头*/ input::-webkit-outer-spin-button, input::-webkit-in ...

  7. iOS---The maximum number of apps for free development profiles has been reached.

    真机调试免费App ID出现的问题The maximum number of apps for free development profiles has been reached.免费应用程序调试最 ...

  8. 有理数的稠密性(The rational points are dense on the number axis.)

    每一个实数都能用有理数去逼近到任意精确的程度,这就是有理数的稠密性.The rational points are dense on the number axis.

  9. [LeetCode] Minimum Number of Arrows to Burst Balloons 最少数量的箭引爆气球

    There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided ...

随机推荐

  1. Yii2.0 Cookies机制和使用方法

    在实际的项目开发过程中,用到了Yii2.0 Cookies机制!但是遇到一个十分奇葩的问题,同一个YII框架,backend下Cookies能够正常存储于客户端,但是frontend始终不行.文章的最 ...

  2. SQL增删查改语句

    一.增:有4种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> insert into sheet1 va ...

  3. ubuntu 14.04 安装tomcat服务器 配置图片路径和文件路径

    root@hett-PowerEdge-T30:/usr/local/src# lltotal 235956drwxr-xr-x  6 root root      4096  3月 26 14:48 ...

  4. URL URI URN的区别

    下面这张图可以完美的解释他们三者之间的关系 URI包含URL和URN Uniform Resource Identifier :统一资源标志符,用于标识某一互联网资源 Uniform Resoutce ...

  5. 获取url请求的参数值

    function getURLParameter(name) { return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '( ...

  6. 各种分布(distribution)

    正态分布(Normal distribution),又名高斯分布(Gaussian distribution).若随机变量X服从一个数学期望为μ.方差为σ^2(标准差为σ)的正态分布,记为N(μ,σ^ ...

  7. 爬虫_python3_requests

    Requests 网络资源(URLs)撷取套件 改善Urllib2的缺点,让使用者以最简单的方式获取网络资源 可以使用REST操作(POST,PUT,GET,DELETE)存取网络资源 import ...

  8. js获取主机名实现页面跳转

    <script language="javascript" type="text/javascript">        var hostname ...

  9. 洛谷 P1214 等差数列

    https://www.luogu.org/problemnew/show/P1214 首先暴力枚举可以凑出来的数,对于每个数进行标记. 对于每一个等差数列,当我们知道前两个数后即可以得出整个序列,那 ...

  10. CF547D Mike and Fish 建图

    题意: 有点长→CF547DMike and Fish. 分析: 其实也没什么好分析的,我这也是看的题解. (不过,那篇题解好像文字的代码不太对劲) 这里直接说做法,正确性自证: 对输入的,将横.纵坐 ...