HDU 1536 SNim

HDU_1536

    比较直观的思路将每一堆的sg函数计算出来,然后看所有的sg函数异或之后是否为0。但实际上我们没必要每一堆都独立计算一遍sg函数,因为游戏规则是一样的,所以sg函数也必然是一样,所以只用开一个一维的sg[]数组记录sg函数的值即可。

    此外,一开始调用一下类似dp(10000)的递归函数企图预处理出sg[]的所有值的想法是错误的,因为假定初始石子是10000个的话,有些情况是可能取不到的,比如样例1,假定初始石子是10000个的话对于9999个石子的情况就没法取到。所以一个比较好的方式就是采用记忆化搜索的形式,用哪个就搜哪个。

    用于记录后继结点sg函数值的数组最好开成静态的放在递归函数外面,这样能节省一些时间。

#include<stdio.h>
#include<string.h>
#define MAXS 110
#define MAXD 10010
int K, M, N, sg[MAXD], s[MAXS], h[MAXD][MAXS];
int dfs(int n)
{
int i, j, k;
if(sg[n] != -1)
return sg[n];
for(i = 0; i < K; i ++)
if(n - s[i] >= 0)
h[n][dfs(n - s[i])] = 1;
for(i = 0; h[n][i]; i ++);
return sg[n] = i;
}
void init()
{
int i, j, k;
for(i = 0; i < K; i ++)
scanf("%d", &s[i]);
memset(sg, -1, sizeof(sg));
memset(h, 0, sizeof(h));
}
void solve()
{
int i, j, k, ans;
scanf("%d", &M);
for(i = 0; i < M; i ++)
{
scanf("%d", &N);
ans = 0;
for(j = 0; j < N; j ++)
{
scanf("%d", &k);
ans ^= dfs(k);
}
printf("%c", ans == 0 ? 'L' : 'W');
}
printf("\n");
}
int main()
{
for(;;)
{
scanf("%d", &K);
if(!K)
break;
init();
solve();
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2366406.html