Number Game_状态压缩

Description

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.)

Input

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.

Output

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.

Sample Input

2 2 5
2 2 3
5 2 3 4 5 6
0

Sample Output

Test Case #1
The winning moves are: 2

Test Case #2
There‘s no winning move.

Test Case #3
The winning moves are: 4 5 6

【题意】两个人玩游戏,给出2~20中的几个数,取出一个数后去掉该数,其倍数也去掉,已经去掉的数和当前的数相加的和如果存在数组中也去掉;

求先选哪些数会赢;

【思路】

状态压缩

要从一个状态里去掉某个位置的数  state&=~(1<<(i))

要给一个状态加入某个位置的数state|=(1<<i)

判断一个状态里是否包含某个位置的数 if(state&(1<<i))  为1则包含

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[1<<19];
int get_ans(int state,int x)
{
    int tmp=state;
    for(int i=x; i<=20; i+=x)//将倍数去掉;
    {
        tmp&=~(1<<(i-2));
    }
    for(int i=2; i<=20; i++)//假设某个数在这个集合里,那么用它不断减去x, 如果得到的差值不在这个集合里,那么这个数是非法的,所以要去掉。
    {
        if(tmp&(1<<(i-2)))
            for(int j=x; i-j-2>=0; j+=x)
            {
                if(!(tmp&(1<<(i-j-2))))
                {
                    tmp&=~(1<<(i-2));
                    break;
                }
            }
    }
    return tmp;
}
int dfs(int state)
{
    if(dp[state]!=-1) return dp[state];
    for(int i=2; i<=20; i++)
    {
        if(state&(1<<(i-2)))
        {
            if(dfs(get_ans(state,i))==0)//等于零说明没得选了,赢了
                return dp[state]=1;
        }
    }
    return dp[state]=0;
}
int main()
{
    int cas=1;
    int a[25],n;
    while(scanf("%d",&n)!=EOF,n)
    {
        int state=0;
        memset(dp,-1,sizeof(dp));
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            state|=(1<<(a[i]-2));
        }
        printf("Test Case #%d\n",cas++);
        if(!dfs(state)) printf("There‘s no winning move.");
        else
        {
            printf("The winning moves are:");
            for(int i=1; i<=n; i++)
            {
                if(dfs(get_ans(state,a[i]))==0)
                    printf(" %d",a[i]);
            }

        }
        cout<<endl<<endl;
    }
    return 0;
}
时间: 2024-11-05 23:37:13

Number Game_状态压缩的相关文章

POJ1143:Number Game(状态压缩)

Description 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 nu

POJ 1143 Number Game 状态压缩dp

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <vector> #include <cstri

uva 11195 Another queen (用状态压缩解决N后问题)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2136 Problem A Another n-Queen Problem I guess the n-queen problem is known by every person who has studied backtracking. In this problem you s

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

Victor and World(spfa+状态压缩dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 958    Accepted Submission(s): 431 Problem Description After trying hard fo

poj 3311 Hie with the Pie(状态压缩dp)

Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be

HDU 5418——Victor and World——————【状态压缩+floyd】

Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 891    Accepted Submission(s): 399 Problem Description After trying hard for many years, Victor has finally received a pilot li

poj 3254 Corn Fields(状态压缩dp)

Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and

Codeforces544E:Remembering Strings(状态压缩)

You have multiset of n strings of the same length, consisting of lowercase English letters. We will say that those strings are easy to remember if for each string there is some position i and some letter c of the English alphabet, such that this stri