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. swagger搭建(基于springBoot)详解

    前后端分离后,api接口文档的维护就成了一个让人头疼的问题,api接口更新慢,或因开发工作量大,没时间整理文档,导致前后端分离后前端同学和后端同 学都纠结于文档的问题.而swagger的出现,不亚于一 ...

  2. expdp ORA-39070:Unable to open the log file

    Oracle中,当执行expdp或impdp的时候,有时候会出现错误: [oracle@bi-dw ~]$ expdp dp_user/dp_password@dw directory=expdp_d ...

  3. Gradle 中 buildConfigField的巧妙应用

    当用AndroidStudio来进行Android项目开发时,build.gradle就是这个工具的核心部分,所有的依赖,debug/release设置,混淆等都在这里进行配置. 下面就主要来记录下利 ...

  4. OpenCV 学习笔记 06 SIFT使用中出现版权问题error: (-213:The function/feature is not implemented)

    1 错误原因 1.1 报错全部信息: cv2.error: OpenCV(4.0.1) D:\Build\OpenCV\opencv_contrib-4.0.1\modules\xfeatures2d ...

  5. unity, 在image effect shader中用_CameraDepthTexture重建世界坐标

    --------------更新 更简单的方法: //depth: raw depth, nonlinear, 0 at near plane, 1 at far plan   float4 scre ...

  6. Instrumentation 功能介绍(javaagent)

    利用 Java 代码,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中 ...

  7. C++复数运算 重载

    近期整理下很久前写的程序,这里就把它放在博文中了,有些比较简单,但是很有学习价值. 下面就是自己很久前实现的复数重载代码,这里没有考虑特殊情况,像除法中,分母不为零情况. #include <i ...

  8. Asp.Net 导入Excel自动获取表名

    public static DataSet ReadExcel(string Path, string fileType) { //服务器需要安装驱动 //http://download.micros ...

  9. Oracle---number数据类型

    NUMBER ( precision, scale)  precision表示数字中的有效位;如果没有指定precision的话,Oracle将使用38作为精度.  如果scale大于零,表示数字精确 ...

  10. hdoj:2040

    #include <iostream> #include <vector> using namespace std; vector<long> yueShu(lon ...