首页 > 代码库 > Laoj P1356 伊甸园日历游戏

Laoj P1356 伊甸园日历游戏

试题描述
  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先操作,问他有没有必胜策略?
输入格式
  一个测试点。多组数据。
  第一行为数据组数。
  接下来一行X Y Z表示X年Y月Z日
输出格式
  输出“YES”or“NO”表示亚当是否有必胜策略。 
输入示例
3
2001 11 3
2001 11 2
2001 10 3
输出示例
YES
NO
NO
试题来源
From ZJU

 

【分析】

博弈论+记忆化搜索。

乍一看有点懵,分析一下可以简化,每个状态可以向下分成两个新状态,只要在这其中的一个状态是不合法的,就等于把这个不合法的状态给了对手,那么自己就是必赢的。

这题的数据有点坑,其中有本来就不合法(在2011.11.4之后)的,所以要先判断一下。

 

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t, a, b, c, x, y, z;
 5 int f[2015][15][35];
 6 int m[13]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 7 
 8 int fun(int a) {
 9     return (a%400==0 || (a%4==0 && a%100));
10 }
11 
12 bool check(int x, int y, int z) {
13     if (x>2001)
14         return false;
15     if (x==2001 && ((y==11 && z>4)||y==12))
16         return false;
17     return true;
18 }
19 
20 void get1(int &x, int &y, int &z) {
21     int maxx=m[y];
22     if (y==2)
23         maxx+=fun(x);
24     if (z>maxx)
25         y++, z=1;
26     if (y>12)
27         x++, y=1;
28     return;
29 }
30 
31 void get2(int &x, int &y, int &z) {
32     if (y>12)
33         x++, y-=12;
34     int maxx=m[y];
35     if (y==2)
36         maxx+=fun(x);
37     if (z>maxx) {
38         x=2002;
39         return;
40     }
41     return;
42 }
43 
44 int dfs(int a, int b, int c) {
45     if (a==2001 && b==11 && c==4)
46         return f[a][b][c]=0;
47     if (f[a][b][c]!=-1)
48         return f[a][b][c];
49     if (!check(a, b, c))
50         return f[a][b][c]=1;
51     x=a, y=b, z=c;
52     z++; get1(x, y, z);
53     if (!dfs(x, y, z))
54         return f[a][b][c]=1;
55     x=a, y=b, z=c;
56     y++; get2(x, y, z);
57     if (!dfs(x, y, z))
58         return f[a][b][c]=1;
59     return f[a][b][c]=0;
60 }
61 
62 int main() {
63     cin >> t;
64     memset(f, -1, sizeof(f));
65     for (int i=1;i<=t;++i) {
66         cin >> a >> b >> c;
67         if (!check(a, b, c)) {
68             cout << "NO" << endl;
69             continue;
70         }
71         if (f[a][b][c]==-1)
72             dfs(a, b, c);
73         if (f[a][b][c])
74             cout << "YES" << endl;
75         else
76             cout << "NO" << endl;
77     }
78 }

 

Laoj P1356 伊甸园日历游戏