#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <cstring>
#define INF 100000000
using namespace std;
int ans[30];
int a[30];
int d[(1<<20)+10];
int fun(int dp){
if(dp == 0)
{
return d[0] = 0;
}
if(d[dp] != -1)
{
return d[dp];
}
d[dp] = 0;
for(int i = 2; i <= 20;i++){
int state = dp;
if(state & (1 << (i-1))){
for(int j = 2;j <= 20;j++){
if(!(state&(1 <<(j-1)))){
for(int k = 1;k * i <= 20;k++){
for(int w = 1;k * i + w * j <= 20;w++ ){
int q = k * i + w *j;
if(state&(1 << (q-1))){
state ^= (1 <<(q-1));
}
}
}
}
}
int k = i;
while(k <= 20){
if(state&(1 << (k-1))){
state ^= (1 <<(k-1));
}
k+=i;
}
d[dp] |= !fun(state);
}
}
return d[dp];
}
int main(){
int n;
int q = 1;
memset(d,-1,sizeof(d));
while(scanf("%d",&n),n){
int dp = 0;
for(int i = 0;i < n;i++){
scanf("%d",&a[i]);
dp ^= (1 << (a[i]-1));
}
memset(ans,0,sizeof(ans));
for(int i = 0;i < n;i++){
int state = dp;
//寻找他对手的可能的状态
for(int j = 2;j <= 20;j++){
if(!(state&(1 <<(j-1)))){
for(int k = 1;k * a[i] <= 20;k++){
for(int w = 1;k * a[i] + w * j <= 20;w++ ){
int g = k * a[i] + w *j;
if(state&(1 << (g-1))){
state ^= (1 <<(g-1));
}
}
}
}
}
int k = a[i];
while(k <= 20){
if(state&(1 << (k-1))){
state ^= (1 <<(k-1));
}
k += a[i];
}
ans[a[i]] = !fun(state);//他的状态取决于他对手是否存在有一个必输态
}
queue<int> que;
for(int i = 2;i <= 20;i++){
if(ans[i] == 1){
que.push(i);
}
}
printf("Test Case #%d\n",q++);
if(!que.empty()){
cout << "The winning moves are:";
while(!que.empty()){
cout <<" "<< que.front();
que.pop();
}
cout << endl;
}
else{
cout << "There's no winning move." << endl;
}
cout << endl;
}
return 0;
}
POJ 1143 Number Game 状态压缩dp
最新推荐文章于 2018-12-05 15:05:00 发布