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. 解决javah生成c头文件时找不到android类库的问题

    问题描述: cmd下面进入工程的bin/classes下面,执行 javah xxx.xxx.A 生成头文件, 一般来说都是可以成功执行的,但是如果xxx.xxx.A类里面引用了android类库里面 ...

  2. 链接选项-rpath的一个问题记录

    问题简述 大概是这么一个情况,有一个过去已经写好的程序,这个程序用于处理网络通信,接收一些操作指令.具体的指令操作通过运行时加载动态库的形式进行扩展.(类似于net-snmp二次开发的一种形式) 问题 ...

  3. easyui tab上面添加右键菜单

    说扩展,我觉得有点过了,只是加入了右击TAB选项卡时显示关闭的上下文菜单,先看下效果图: 具体实现代码: 右键菜单 HTML: <div id="mm" class=&quo ...

  4. 使用DIV弹出框的代码示例,备忘。

    1.思路 使用DIV模拟弹出框,一共用三个div: divWindow: 原来的界面内容区域 divLogin:要弹出的内容区域 divBackground:给弹出内容区域做个遮罩的区域. 点击 “请 ...

  5. 如何给Elasticsearch安装中文分词器IK

    安装Elasticsearch安装中文分词器IK的步骤: 1. 停止elasticsearch 2.2的服务 2. 在以下地址下载对应的elasticsearch-analysis-ik插件安装包(版 ...

  6. Android 四大组件 Service 服务

    1.Service简单介绍 依照使用范围分类: 类别 优点 缺点 差别 应用 本地服务 Local  Service 本地服务在一定程度上节约了资源,另外本地服务由于是在同一进程,因此不须要IPC,也 ...

  7. Socket网络编程--聊天程序(2)

    上一节简单如何通过Socket创建一个连接,然后进行通信.只是每个人只能说一句话.而且还是必须说完才会接收到信息,总之是很不方便的事情.所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话 ...

  8. 当visual studio的数据库项目遇到SQL71501

    这是因为数据库项目缺少login用户. 加上就好了,注意要加sql server用户. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5 ...

  9. 【转】Ubuntu FireFox无法播放网页视频音乐的解决办法

    原文:http://www.codeweblog.com/%E8%A7%A3%E5%86%B3qq%E9%9F%B3%E4%B9%90%E7%BD%91%E9%A1%B5%E7%89%88%E5%9C ...

  10. 【C】——实现tree命令

    在大部分的linux系统中有一个很好用的命令——tree,就是显示目录的结构,但是发现在FreeBSD中没有这个命令,因此自己实现了一个简单的tree.代码如下:主要利用了递归的思想. #includ ...