POJ 1082 Calendar Game 找规律博弈(存在特殊情况)

Calendar Game
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 4634 Accepted: 2179

Description

Adam and Eve enter this year's ACM International Collegiate Programming Contest. Last night, they played the Calendar Game, in celebration of this contest. This game consists of the dates from January 1, 1900 to November 4, 2001, the contest day. The game starts by randomly choosing a date from this interval. Then, the players, Adam and Eve, make moves in their turn with Adam moving first: Adam, Eve, Adam, Eve, etc. There is only one rule for moves and it is simple: from a current date, a player in his/her turn can move either to the next calendar date or the same day of the next month. When the next month does not have the same day, the player moves only to the next calendar date. For example, from December 19, 1924, you can move either to December 20, 1924, the next calendar date, or January 19, 1925, the same day of the next month. From January 31 2001, however, you can move only to February 1, 2001, because February 31, 2001 is invalid. 

A player wins the game when he/she exactly reaches the date of November 4, 2001. If a player moves to a date after November 4, 2001, he/she looses the game. 

Write a program that decides whether, given an initial date, Adam, the first mover, has a winning strategy. 

For this game, you need to identify leap years, where February has 29 days. In the Gregorian calendar, leap years occur in years exactly divisible by four. So, 1993, 1994, and 1995 are not leap years, while 1992 and 1996 are leap years. Additionally, the years ending with 00 are leap years only if they are divisible by 400. So, 1700, 1800, 1900, 2100, and 2200 are not leap years, while 1600, 2000, and 2400 are leap years.

Input

The input consists of T test cases. The number of test cases (T ) is given in the first line of the input file. Each test case is written in a line and corresponds to an initial date. The three integers in a line, YYYY MM DD, represent the date of the DD-th day of MM-th month in the year of YYYY. Remember that initial dates are randomly chosen from the interval between January 1, 1900 and November 4, 2001.

Output

Print exactly one line for each test case. The line should contain the answer "YES" or "NO" to the question of whether Adam has a winning strategy against Eve. Since we have T test cases, your program should output totally T lines of "YES" or "NO".

Sample Input

3 
2001 11 3 
2001 11 2 
2001 10 3 

Sample Output

YES
NO
NO

Source


题意是说Adam和 Eve玩日历游戏,在1990年的1月1号到2001年的11月4号之间随机出一个日期,两人轮流移动日期,要求只能往此日期的下一天移动或者下个月的这一天移动(如果下个月没有这一天,则不能移动)如果谁先移动2001年的11月4号,谁就获胜。一下是网上的结题思路,看完之后,跪了。

博弈论题目可以用寻找必败状态的方法解决。

   

第一个必败状态是2001.11.04。由此可以推出其他任何时间的状态。对于除2001.11.04外的其他任何时间,present状态是由能移动到的下两个next状态决定的(当然有些时间只有一个next状态),比如1924.12.19的状态是由1924.12.20和1925.01.19两个状态决定。如果两个next状态中有一个必败状态,则present状态为必胜状态;如果两个next状态都为必胜状态,则present状态为必败状态。

   

对于2001年11月的那4天,状态都是交替胜负的。1和3号必胜,2和4号必败。现在考虑10月份,5-31号只有一个next状态,推算可知奇数号状态为必败,偶数号状态为必胜。1-4号状态有两个next状态,推算可知也是奇数号状态为必败,偶数号状态为必胜。也就是说整个10月份奇数号状态为必败,偶数号状态为必胜。

   

由此我们可以推测如果每个月都是31天的话,那么每天的状态都是相反的,而且相邻的两个月的同一天状态也是相反的。即奇数月的奇数号状态为必胜,偶数号专题为必败;偶数月偶数号状态为必胜,奇数号状态为必败。从数学上说,就是月与号和为偶数的天状态为必胜,为奇数的天状态为必败。显然这个是成立的,可以自己推算一下。

   

接下来要考虑特殊情况,那几个只有30天的月份。有30号的有4,6,9,11这四个月。对于04.30,next状态有05.01和05.30,显然两个next状态是相反的,所以04.30的状态是必胜的。所以04.30的状态情况符合上面那个结论。06.30同样如此。对于09.30,next状态有10.01和10.30,同样10.01和10.30的状态是相反的,所以09.30的状态为必胜,这不符合上面的结论。但是我们可以证明这只是一种特殊情况,不影响整个结论。按照原来的结论,九月份的奇数号状态为必胜,偶数号状态为必败。现在30号的状态变化了,如果我们能证明29号的状态不会因此发生变化,那么特殊情况就只局限于30号了。09.29号的next状态有09.30和10.29,10.29的状态为必败,所以09.29的状态为必胜,还是符合原来的结论。11.30同样如此。

   

最后考虑特殊的2月份。如果是闰年的29天,效果和31天一个月是一样的(只要是奇数都一样,哪怕一个月只有一天)。对于非闰年,2月只有28天。其实28天也等同于30天的情况,推算可知02.28和04.30,06.30一样,不影响整个结论。

   

总结,月与号和为偶数的天状态为必胜,为奇数的天状态为必败。特殊情况为09.30和11.30,这两天的状态也为必胜。


#include<stdio.h>
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int y,m,d,win=0;
        scanf("%d%d%d",&y,&m,&d);
        if((m+d)%2)win=1;
        if(d==30&&(m==9||m==11))win=0;
        if(win==1)printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值