题目链接:HDU 1536 S-Nim
尼姆博弈。
题目说的很乱,其实比较简单,打个sg表就行了。
错了几次。哎。模版都没用明白。具体看这里吧。
今天下午(2014.4.14)重新做了下这道题 ,感觉用递归写sg函数更好理解。
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
//#define test
using namespace std;
const int MAX_N = 10000 + 20;
//f[]:可以取走的石子个数
//sg[]:0~n的SG函数值
//hash[]:mex{}
int f[110],sg[MAX_N],hash[110];
int k,m,t;
void getSG()
{
int i,j;
memset(sg,0,sizeof(sg));
for(i=1;i<=MAX_N;i++)
{
memset(hash,0,sizeof(hash));
for(j=1;f[j]<=i && j <= k;j++)
hash[sg[i-f[j]]]=1;
for(j=0;j<=MAX_N;j++) //求mes{}中未出现的最小的非负整数
{
if(hash[j]==0)
{
sg[i]=j;
break;
}
}
}
}
int main()
{
#ifdef test
freopen("in.txt","r",stdin);
#endif // test
while(cin >> k,k)
{
int temp;
for(int i = 1;i <= k;i++)
{
cin >> temp;
f[i] = temp;
}
sort(f + 1,f + k + 1);
getSG();
cin >> t;
while(t--)
{
cin >> m;
int ans = 0;
for(int i = 0;i < m;i++)
{
cin >> temp;
ans ^= sg[temp];
}
if(ans)
cout << "W";
else
cout << "L";
}
cout << endl;
}
return 0;
}
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
//#define test
using namespace std;
const int MAX_N = 10000 + 20;
int f[110],sg[MAX_N];
int k,m,t;
int get_SG(int h)
{
if(sg[h] != -1)
return sg[h];
bool vis[110];
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= k && h - f[i] >= 0; i++)
vis[get_SG(h - f[i])] = 1;
for(int i = 0; ; i++)
{
if(!vis[i])
return sg[h] = i;
}
}
int main()
{
#ifdef test
freopen("in.txt","r",stdin);
#endif // test
while(cin >> k,k)
{
memset(sg, -1, sizeof(sg));
int temp;
for(int i = 1;i <= k;i++)
{
cin >> temp;
f[i] = temp;
}
sort(f + 1,f + k + 1);
cin >> t;
while(t--)
{
cin >> m;
int ans = 0;
for(int i = 0;i < m;i++)
{
cin >> temp;
ans ^= get_SG(temp);
}
if(ans)
cout << "W";
else
cout << "L";
}
cout << endl;
}
return 0;
}