【POJ1082】Calendar Game (博弈)
【题目】
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 |
【题意】
从某年某月某天开始两个人轮流开始将日期推进,推进方法有两种,1.推进到第二天 2.推进到下个月的这一天。谁到达2001.11.4谁赢,谁超过了谁输。
【分析】
一开始想到了最暴力的方法,就是递归找状态(应该是能做出来的)。然而看了大神的29行代码后,我方了!!方了!!
先看看大神的思路:
分析:np问题,我们设月号加日号等于d,对于第二种推进方式,会改变d的奇偶性。(因为月的奇偶变了,日的奇偶没变,和的奇偶就变了)。对于第一种推进方式,如果推进后还在同一个月份,那么会改变d的奇偶性。(因为月的奇偶没变,日的变了,和的奇偶就变了)。第一种推进方式,跨月份的时候,有些会改变,有些不会改变。有31天、29天的月份会变,30天、28天的不会变,其中对于d为偶的情况(2月28,4、6月30)可以利用第二中方式变为奇。
由此可见对于绝大部分情况来说d的奇偶是轮流出现的,最终必败态是11月4日奇态。所有的偶态均可到达奇态,对于d为奇的9、11月30也可以到达奇态。其余奇态只能到达偶态。如果把偶态和9.30和11.30划入集合A,其余划入集合B,那么对于A的所有元素均有办法到达集合B。而B中元素只能到达集合A,无法到达集合B。且11.4属于B。所以,A中元素为必胜,B中为必败。(还需仔细考虑快到2001.11.4的那些日子,幸好也没有出现任何意外)
我来试着按着他的思路推一遍。
假设:偶态(日加月为偶数),9.30和11.30为必胜态,其余为必败态。
我们只要证明:
·1、2001.11.4为必败态。(别人给你这个状态相当于别人先一步走到这个状态,你输了)这点显而易见,不需要证明。
·2、所有的必胜态都能到达某一必败态。
·3、所有的必败态都只能到达必胜态。
证明2:所有的必胜态都能到达某一必败态。
1、当为偶态,若能走到下一个月,则能走到必败态。
2、当为偶态,不能走到下一个月,走到下一天,则能走到必败态。
3、当为9.30->10.1,当为11.30->12.1
证明3:所有的必败态(除9.30 11.30的奇态)都只能到达必胜态。
除了那两天,走到下一天还是下一个月都会是偶态。
所以假设成立。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1010 8 9 int main() 10 { 11 int T; 12 scanf("%d",&T); 13 while(T--) 14 { 15 int y,m,d; 16 scanf("%d%d%d",&y,&m,&d); 17 if((m==11||m==9)&&d==30) printf("YES\n"); 18 else if((m%2)==(d%2)) printf("YES\n"); 19 else printf("NO\n"); 20 } 21 return 0; 22 }
2016-04-24 15:01:14