题目:点击打开链接
蓝桥杯的题,寒假的时候看还不会,看了解析也没太理解。这几天基本都在看博弈,就重新看了看这个题。
看了以后第一反应就是用SG函数……用SG函数时间不错,就是比较耗内存。
#include <stdio.h>
#include <string.h>
int sg[10010];
int s[4] = {1, 3, 7, 8};
int getsg(int x)
{
int i;
if(sg[x] != -1)
return sg[x];
bool hash[1010];//之前hash数组开大了。rt了两次
memset(hash, 0, sizeof(hash));
for(i = 0; i < 4; i++)
{
if(x >= s[i])
{
sg[x - s[i]] = getsg(x - s[i]);
hash[sg[x - s[i]]] = 1;
}
}
for(i = 0; i < 1010; i++)
{
if(!hash[i])
break;
}
return sg[x] = i;
}
int main (void)
{
int n;
memset(sg, -1, sizeof(sg));
sg[0] = 1;
sg[1] = 0;
scanf("%d", &n);
while(n --)
{
int m;
scanf("%d", &m);
sg[m] = getsg(m);
printf("sg = %d\n", sg[m]);
if(sg[m] == 0)
printf("0\n");
else
printf("1\n");
}
return 0;
}
另一种方法:
s[i - 1] && s[i - 3] && s[i - 7] && s[i - 8] == 1 的意思是,如果此结点的后继结点中存在必败态,那么为了让对方输,就要将石子减少到相应的必败态以保证“我”是取胜的。如果所有后继结点都是必胜态,那么不管减少到哪个状态,对方都是赢的,”我”就输了。
#include <stdio.h>
int s[10010] = {-1, 0, 1, 0, 1, 0, 1, 0, 1};
int main (void)
{
int n, i;
for(i = 9; i < 10010; i++)
{
if(s[i - 1] && s[i - 3] && s[i - 7] && s[i - 8] == 1)
s[i] = 0;
else
s[i] = 1;
}
scanf("%d", &n);
while(n --)
{
int m;
scanf("%d", &m);
printf("%d\n", s[m]);
}
return 0;
}