Calendar Game HDU - 1079

原题链接

考察:博弈论

思路一:

        dfs记忆化搜索,枚举当前结点能到的每一个点.sg函数记录不能到达的点.

        当sg函数>0,说明有操作时当前点到达0点.此时先手为胜.

思路二:

       上面的思路数据稍微小点,就会报错...

       找规律.观察操作,每次操作使日期的奇偶性改变.终点的日期之和(不考虑年)为偶数,所以我们要保证对方永远在奇数点上.只要我们在偶数点,总有办法使得对方去奇数点.(eg:2.28->3.1(偶数)或3.28(奇数))但是存在两个奇数点也可以取胜,9.30(奇数)->10.30(偶数)或10.1(奇数)和11.30需要特判.

        分析得很好的po主 GO

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 int main()
 5 {
 6     int y,m,d , t;
 7     scanf("%d",&t);
 8     while(t--)
 9     {
10          scanf("%d%d%d",&y,&m,&d);
11          if((m+d)%2==0 || m==9 && d==30 || m==11 && d==30)  printf("YES\n");
12          else printf("NO\n");
13     }
14     return 0;
15 }
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <cstring>
 5 using namespace std;
 6 const int N = 2010,M = 13,D = 32;
 7 int month[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
 8 int f[N][M][D];
 9 bool check(int year)
10 {
11     if(year%400==0||(year%4==0&&year%100!=0)) return 1;
12     return 0;
13 }
14 bool datecheck(int y,int m,int d)
15 {
16     if(y>2001||(y==2001&&m>11)||(y==2001&&m==11&&d>4)) return 0;
17     return 1;
18 }
19 int sg(int y,int m,int d)
20 {
21     if(f[y][m][d]!=-1) return f[y][m][d];
22     if(check(y)) month[2] = 29;
23     else month[2] = 28;
24     set<int> s;
25     if(d+1<=month[m]&&datecheck(y,m,d+1)) s.insert(sg(y,m,d+1));
26     else if(d==month[m]&&m!=12&&datecheck(y,m+1,1)) s.insert(sg(y,m+1,1));
27     else if(d==month[m]&&m==12&&datecheck(y+1,1,1)) s.insert(sg(y+1,1,1));
28     if(m+1<=12&&d<=month[m+1]&&datecheck(y,m+1,d)) s.insert(sg(y,m+1,d));
29     else if(m==12&&d<=month[1]&&datecheck(y,1,d)) s.insert(sg(y+1,1,d));
30     for(int i=0;;i++)
31       if(!s.count(i)) return f[y][m][d] = i;
32 }
33 int main() 
34 {
35     int T;
36     scanf("%d",&T);
37     memset(f,-1,sizeof f);
38     f[2001][11][4] = 0;//先到2001 11 4的为胜 
39     while(T--)
40     {
41         int y,m,d;
42         scanf("%d%d%d",&y,&m,&d);
43         if(sg(y,m,d)) puts("YES");
44         else puts("NO");//if sg返回>0,说明下一步能到0,下一步就赢了 
45     }
46     return 0;
47 }
思路一

 

posted @ 2021-03-22 00:57  acmloser  阅读(20)  评论(0编辑  收藏  举报