HDU 1536 S-Nim

本文深入探讨了HDU_1536问题中动态规划与记忆化搜索的巧妙结合,通过实例分析,解释了如何利用sg函数和异或运算解决复杂的游戏策略问题。文章详细阐述了解决方案的原理、实现过程,并通过代码示例展示了算法的具体应用。

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值