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 }