现在的位置: 首页 > 综合 > 正文

吃糖果游戏(tyvj 1567)

2014年09月29日 综合 ⁄ 共 1942字 ⁄ 字号 评论关闭

tyvj 1567:

博弈,题目给的数据是不超过1000位,所以这题应该找规律求解。

我是将30以内的sg值值求出来,然后规律就很容易看出来啦。

求sg值:

#include <stdio.h>
#include <string.h>

int sg[100][100];

int getsg(int x, int y)
{
	int i;
	if(sg[x][y] != -1)
		return sg[x][y];
	bool vis[100];
	memset(vis, 0, sizeof(vis));
	for(i = 1; i < x; i++)
		vis[getsg(x - i, i)] = 1;
	for(i = 1; i < y; i++)	
		vis[getsg(y - i, i)] = 1;
	for(i = 0; i < 100; i++)
		if(vis[i] == 0)
			break;
	return sg[x][y] = sg[y][x] = i;
}

int main (void)
{
	memset(sg, -1, sizeof(sg));
	int i, j;
	for(i = 0; i < 100; i++)
		sg[1][i] = sg[i][1] = 1;
	
	for(i = 1; i <= 30; i ++)
		for(j = 1; j <= 10; j++)
			getsg(i, j);
	
	//getsg(20, 20);//开始这样写,但是结果不对
	for(i = 1; i <= 30; i ++)
	{
		for(j = 1; j <= 10; j++)
		{
			if(sg[i][j] != 0)
				printf("1 ");
			else
				printf("0 ");
		}
		printf("\n");
	}

	return 0;
}

打出来的结果:

1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 0 0 1 1 1 0 0 1 1
1 0 0 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1

恩 除此之外还有一种思考方式,可以直接找到规律,上面sg函数是以二维来思考的,我们也可以换作一维,那么n,就代表已经将其中一堆吃完,剩下那一堆将要被分割的糖果数是n。

当n = 1时,先手胜。

当n = 2,因为只能分成(1, 1)(胜, 胜), 所以2是必败的。

当n = 3,可以分成(2, 1)(败, 胜),那么后手在面对(2, 1)这个状态的时候肯定是吃掉2这堆,留下1这堆,因为通过前面的分析知道分割1可以保证胜利,这样后手就会赢,所以3是必败的。

当n = 4时, 可以分成(2, 2)(败, 败), (1, 3)(胜, 败),先手肯定要将两个必败态留给对手,所以肯定会选择分成(2, 2)。

当n = 5时, 可以分成(2, 3)(败, 败), (1, 4)(胜, 胜), 先手选择分成(2, 3)保证对手输。

也就是说如果n的后继状态中有一种分法(a, b),其中a和b都是必败的,那么n是必胜的,否则必败。

………………

推个20或者30的应该就可以看出规律:

1     2     3     4     5     6     7     8     9    10   

1     0     0     1     1     1     0     0     1     1     

11  12   13   14  15   16   17  18   19   20

1     0     0     1     1     1     0     0     1     1       

(做题的时候如果头脑清楚思维敏捷,这应该也是不错的方法,但是感觉就是不太适合我_(:з」∠)_)

找到规律就很好写了~

#include <stdio.h>
#include <string.h>

char a[10010], b[10010];

int yes(char x)
{
	if(x == '1' || x == '4' || x == '5' || x == '6' || x == '9' || x == '10')
		return 1;
	return 0;
}

int f(char x)
{
	if(x == '2' || x == '3' || x == '7' || x == '8')
		return 0;
	return 1;
}

int main (void)
{
	while(scanf("%s %s", a, b) != EOF)
	{//只要判断最后一位 
		int len1 = strlen(a), len2 = strlen(b);
		if(yes(a[len1 - 1]) || yes(b[len2 - 1]))
			printf("Matrix67\n");
		else
		{
			if(f(b[len2 - 1]) || f(a[len1 - 1]))
				printf("Matrix67\n");
			else
				printf("Shadow\n");		
		}
			
	}
	return 0;
}

抱歉!评论已关闭.