伊甸园日历游戏

描述 Description

   Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来。然后他们轮流对这个日期进行操作:

   1 : 把日期的天数加1,例如1900.1.1变到1900.1.2

   2 : 把月份加1,例如:1900.1.1变到1900.2.1

   其中如果天数超过应有天数则日期变更到下个月的第1天。月份超过12则变到下一年的1月。而且进行操作二的时候,如果有这样的日期:1900.1.31,则变成了1900.2.31,这样的操作是非法的,我们不允许这样做。而且所有的操作均要考虑历法和闰年的规定。

   谁先将日期变到2001.11.4谁就赢了。

   每次游戏都是Adam先操作,问他有没有必胜策略?

输入格式 InputFormat

  一个测试点。多组数据。
  第一行为数据组数。
  接下来一行X Y Z表示X年Y月Z日

输出格式 OutputFormat

  输出“YES”or“NO”表示亚当是否有必胜策略。 

样例输入 SampleInput 

3
2001 11 3
2001 11 2
2001 10 3

样例输出 SampleOutput 

YES
NO
NO

数据范围和注释 Hint

  建议先把所有情况都算出来^_^
思路:
这题那叫一个坑啊, 思路很简单, 但实现起来要考虑的
东西太多了, 终于搞出来了。。。
必败态和胜态有着如下性质:
1、若面临末状态者为获胜则末状态为胜态否则末状态为
必败态。?

2、一个局面是胜态的充要条件是该局面进行某种决策后
会成为必败态。?

3、一个局面是必败态的充要条件是该局面无论进行何种
决策均会成为胜态?

这三条性质正是博弈树的原理,但博弈树是通过计算每
一个局面是胜态还是 必败态来解题,这样在局面数很多
的情况下是很难做到 的,此时,我们可以 利用人脑的推
演归纳能力找到必败态的共性,就可以比 较好的解决此
类问题了。
#include<stdio.h>

int date[110][13][35], run[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, ping[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int isrun(int year)
{
	if(year % 400 == 0)
	{
		return 1;
	}
	if(year % 4 == 0 && year % 100 != 0)
	{
		return 1;
	}
	return 0;
}

int markmonth(int year, int month, int day)
{
	if((year == 2001 && month == 11 && day > 4) || (year == 2001 && month >= 12))
	{
		return 1;
	}
	if(month > 12)
	{
		month = 1;
		year = year+1;
	}
	if(isrun(year))
	{
		if(day <= run[month])
		{
			return date[year-1900][month][day];
		}
	}
	else
	{
		if(day <= ping[month])
		{
			return date[year-1900][month][day];
		}
	}
	return 1;
}
int markday(int year, int month, int day)
{
	if(year == 2001 && month >= 12)
	{
		return 1;
	}
	if(isrun(year))
	{
		if(day > run[month])
		{
			day = 1;
			if(month == 12)
			{
				month = 1;
				year += 1;
			}
			else
			{
				month += 1;
			}
		}
	}
	else
	{
		if(day > ping[month])
		{
			day = 1;
			if(month == 12)
			{
				month = 1;
				year += 1;
			}
			else
			{
				month += 1;
			}
		}
	}
	return date[year-1900][month][day];	
}

int getdp()
{
	date[2001-1900][11][4] = 0;
	int year = 2001, month = 11, day = 3;
	while(year >= 1900)
	{
		if(day < 1)
		{
			if(month-1 < 1)
			{
				day = 31;
				month = 12;
				year = year - 1;
			}
			else
			{
				if(isrun(year))
				{
					day = run[month-1];
					month = month-1;
				}
				else
				{
					day = ping[month-1];
					month = month-1;
				}
			}
		}
		if(!markmonth(year, month+1, day) || !markday(year, month, day+1))
		{
			date[year-1900][month][day] = 1;
		}
		day--;
	}
	return 0;
}

int main()
{
//	freopen("input.txt", "r", stdin);
	getdp();
	int year, month, day, n;
	scanf("%d", &n);
	while(n--)
	{
		scanf("%d%d%d", &year, &month, &day);
		if(date[year-1900][month][day])
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}
	return 0;
}


你可能感兴趣的:(博弈)