#include <cstdlib>
#include <iostream>
#include <list>
#define MAX (1024*512)
using namespace std;
int BIT[19];
int win[MAX];
void PrintBit(int a)
{
int k = 1;
for (int i = 31; i>=0; i--)
if ( (k << i) & a ) cout<<"1";
else cout<<"0";
cout<<endl;
}
void Take(int& set, int pos)
{
//去掉倍数
for (int a = pos + 2; a < 21; a += pos + 2)
if (set & BIT[a-2]) set &= ~(BIT[a-2]);
//去掉倍数之和
int x = ~set;
for (int a = 0; a < 19; a++)
if (x & BIT[a])
for (int b = pos+2; b + a < 21; b += pos+2)
if ( set & BIT[a+b])
set &= ~(BIT[a+b-2]);
}
//返回值意义 :
// -1 未计算
//0 无必胜步
// 第i位为1表示去掉 i为胜步
int WinMoves(int set)
{
//cout<<"Set: "; PrintBit(set);
if (win[set] > -1) return win[set];
win[set] = 0;
for (int pos = 0; pos < 19; pos++)
{
if (BIT[pos] & set)
{
int tkd;
int oldSet = set;
Take(set, pos, tkd); //尝试选取
//cout<<"Set: "; PrintBit(set);
int l = WinMoves(set);
if (l == 0) win[oldSet] |= BIT[pos];
set = oldSet;
}
}
return win[set];
}
int SetCode()
{
int n, a, code = 0;
cin>>n;
for (int i = 0; i < n; i++)
{
cin>>a;
code |= BIT[a-2];
}
return code;
}
int main(int argc, char *argv[])
{
BIT[0] = 1;
for (int i = 1; i < 19; i++)
BIT[i] = BIT[i-1]<<1;
// for (int i = 0; i < 19; i++)
// cout<<"BIT["<<i<<"]="<<BIT[i]<<" ";
// cout<<endl;
win[0] = 0;
for (int i = 1; i < MAX; i++) win[i] = -1;
int t;
cin >> t;
for (int i = 1; i <= t; i++)
{
cout<<"Scenario #"<<i<<":"<<endl;
int res = WinMoves(SetCode());
if (res == 0)
{
cout<<"There is no winning move."<<endl;
}
else
{
cout<<"The winning moves are:";
for (int i = 0; i < 19; i++)
if (BIT[i] & res) cout<<" "<<i+2;
cout<<"."<<endl;
}
cout<<endl;
}
getchar(); getchar();
}
ZOJ 1039 尚未解决
最新推荐文章于 2017-05-15 21:56:19 发布