asdfaskdjgasljgd

lajsdgljasldfjlsj

lajsdlgjasldf

asdljgalsjdg

Time Limit: 1000MS Memory Limit: 65536K

Total Submissions: 3432 Accepted: 1399
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
Source

Mid-Central European Regional Contest 2000

题目的意思就是:有一个不到20的数列,两个人一次选择一个数字。选择完一个数字之后,这个数字的倍数,以及这个数字和前面选过的数字之和,都不可以再选。给你一串数列,问你有没有必胜的选择,就是当前选择这个数字之后,无论对方选择什么都是死!!

解题思路:非常像博弈的题目啊,可是这道题目的标签是状态压缩,当然不是我原创的,我一开始也不会啊,看来别人的博客才知道怎么去写。其实看别人博客,也是学习acm的必经之路,不是吗?只是看完之后你得有自己的思考!!
状态压缩:由于数列不到20,可以用二进制压缩,比如这样一个数列 2 3 5 那么二进制表示就是110100000….
这样的话,一个数列就可以用一个数字来表示。这就是状态压缩的好处,试想想,没有状态压缩,表示一个数列:234567891011… 或者用一个数组表示。。这些都太麻烦啦。
其次:状态压缩我是可以想到的,但是怎么解决这个问题呢,我一直在想动态规划,每个数列可以用0表示是必胜的数列,1表示不是必胜的数列,然后数列可以逐个递推!对,没错,思路是这样,但是你看代码,其实用深度优先搜索,并没有动态规划的形式,用搜索之所以可以,是因为记忆化搜索,即只要有一个状态确定是0或者1,那么就不用对它进行搜索,这样就会非常快。
动态规划的两种方式实现,一个是递推,另一个就是记忆化搜索。二者都是遍历了所有情况

关于状态压缩和位运算
http://blog.csdn.net/Dacc123/article/details/50974579

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdlib.h> using namespace std;
int dp[1<<20];
int n;
int a[25];
int s[25];
//这个函数是把这个二进制数列变成数字,就是将数列压缩成数字来
int getNum(int a[])
{
int res=0;
for(int i=2;i<=20;i++)
{
if(a[i])
res|=1;
res<<=1;
}
return res;
} int dfs(int s[],int st)
{
int v[25];
memcpy(v,s,25*sizeof(int));
v[st]=0;
//把i的倍数,与之前选过的数字之和,都标记成0
for(int i=2;i+st<=20;i++)
{
if(!v[i])
v[i+st]=0;
}
int ss=getNum(v);
//记忆化搜索,这里大幅度提高效率
if(dp[ss]!=0)
{
if(dp[ss]>0)
return 1;
else
return 0;
}
for(int i=2;i<=20;i++)
{
if(v[i]&&!dfs(v,i))
{
dp[ss]=1;
return 1;
}
}
dp[ss]=-1;
return 0;
}
int main()
{
int ans[25];
int b;
memset(dp,0,sizeof(dp));
int cas=0;
while(scanf("%d",&n)!=EOF)
{
cas++;
memset(a,0,sizeof(a));
if(n==0)
break;
for(int i=0;i<n;i++)
{
scanf("%d",&b);
a[b]=1;
}
int tot=0;
for(int i=2;i<=20;i++)
{
if(a[i]&&!dfs(a,i))
ans[tot++]=i;
}
printf("Test Case #%d\n",cas);
if(tot==0)
{
printf("There's no winning move.\n"); }
else
{
printf("The winning moves are: ");
for(int i=0;i<tot;i++)
{
if(i!=tot-1)
printf("%d ",ans[i]);
else
printf("%d\n",ans[i]);
}
}
printf("\n"); }
return 0;
}

POJ-1143(状态压缩)的更多相关文章

  1. poj 3254(状态压缩+动态规划)

    http://poj.org/problem?id=3254 题意:有一个n*m的农场(01矩阵),其中1表示种了草可以放牛,0表示没种草不能放牛,并且如果某个地方放了牛,它的上下左右四个方向都不能放 ...

  2. POJ 1185 状态压缩DP(转)

    1. 为何状态压缩: 棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围.故想到用int s[num].至于开多大的数组,可以自己用DFS搜索试试看:也可 ...

  3. POJ 1185 状态压缩DP 炮兵阵地

    题目直达车:   POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...

  4. poj 1324 状态压缩+bfs

    http://poj.org/problem?id=1324 Holedox Moving Time Limit: 5000MS   Memory Limit: 65536K Total Submis ...

  5. poj 2923(状态压缩dp)

    题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数. 分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法: ...

  6. poj 2688 状态压缩dp解tsp

    题意: 裸的tsp. 分析: 用bfs求出随意两点之间的距离后能够暴搜也能够用next_permutation水,但效率肯定不如状压dp.dp[s][u]表示从0出发訪问过s集合中的点.眼下在点u走过 ...

  7. Mondriaan's Dream(POJ 2411状态压缩dp)

    题意:用1*2的方格填充m*n的方格不能重叠,问有多少种填充方法 分析:dp[i][j]表示i行状态为j时的方案数,对于j,0表示该列竖放(影响下一行的该列),1表示横放成功(影响下一列)或上一列竖放 ...

  8. poj 2411 状态压缩dp

    思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个.这样就可以先把所有的合法状态找到.由于没一层的合法状态都是一样的,那么可以用一个数组保存.由第i-1行到第i行的状态转 ...

  9. poj 3254 状态压缩DP

    思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k]: 这个方程得 ...

  10. POJ 2411 状态压缩递,覆盖方案数

    无非就是横着放与竖着放,状态中用1表示覆盖,0表示未覆盖. #include <iostream> #include <vector> #include <algorit ...

随机推荐

  1. 【HTML打印】HTML直接调用window下的打印机并执行打印任务(简单打印任务生成)

    1.<button onclick="preview('data');" id="print">打印</button> 2. 3.js: ...

  2. shell脚本死循环检查是否有特定的路由,若存在进行删除操作

    while [ 1 ] do tun0_route=`ip route |grep -ci "100.100.80.0"` if [ $tun0_route -eq 0 ];the ...

  3. JSP 性能优化

    无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成.JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长.浏览器在下载和执行 ...

  4. redis-desktop-manager 的简单使用

    1:安装比较简单,所有软件几乎都一样(下载.安装)我就从安装好后,怎么玩记录吧!如下图,双击对应的图标就能打开此软件了 2-1:连接redis服务器的方式之一——导入对应的redis信息 连接配置的样 ...

  5. javascript promises powered by BlueBird

    什么是promises? 为什么需要promises? 参见: https://promisesaplus.com/ 使用示例: 使用promises之前,代码的编写方式: 使用promises之后: ...

  6. Effective Java 第三版——51. 仔细设计方法签名

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  7. goland激活码

    http://idea.youbbs.org      

  8. loadrunner 关联匹配多个值

    loadrunner 关联获取从服务器返回相关值,如果需要把所有匹配的值都获取并且把这些值打印出来,怎么做呢? 1.首先要把把所有的匹配值都保存起来,需要在关联函数里面多传递一个参数:"Or ...

  9. ubuntu 16 安装 openjdk 8

    apt--jdk -y 进行验证即可

  10. 开发FTP不要使用sun.net.ftp.ftpClient

    转自:http://cai21cn.iteye.com/blog/700188 在开发一个web应用过程中,需要开发一个服务使用ftp功能将数据传输一个网外的ftp服务器.最初使用sun.net.ft ...