[关闭]
@IOU 2018-06-09T12:14:04.000000Z 字数 1005 阅读 1176

P1512 伊甸园日历游戏 

博弈论 DP 考试 记忆化搜索

题目

思路

初始状态是对方超过目标年月日就是己方赢,所以目标时间之后的范围都可以初始化为1。然后转移就是两种跳法如果有一种可以跳到对手必败的日期上,那这个日期就是必胜日期。一步一步逆推就好了。注意判闰年。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<vector>
  7. #define ll long long
  8. using namespace std;
  9. int cal[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
  10. int g[115][14][33];
  11. int jum1(int x,int y,int z)
  12. {
  13. z++;
  14. int start=cal[y];
  15. if(x%4==0&&y==2&&x!=0)start=29;
  16. if(z>start)z=1,y++;
  17. if(y==13)y=1,x++;
  18. return g[x][y][z];
  19. }
  20. int jum2(int x,int y,int z)
  21. {
  22. y++;
  23. if(y==13)y=1,x++;
  24. int start=cal[y];
  25. if(x%4==0&&y==2&&x!=0)start=29;
  26. if(start<z)return 1;
  27. return g[x][y][z];
  28. }
  29. int main()
  30. {
  31. int year,month,day;
  32. for(int i=5;i<=31;i++)g[101][11][i]=1;
  33. for(int i=1;i<=31;i++)g[101][12][i]=1;
  34. for(int i=101;i>=0;i--)
  35. {
  36. for(int j=12;j>=1;j--)
  37. {
  38. int start=cal[j];if(i%4==0&&j==2&&i!=0)start=29;
  39. for(int k=start;k>=1;k--)
  40. {
  41. if(i==101&&j==11&&k>=4)continue;
  42. g[i][j][k]=!(jum1(i,j,k)&jum2(i,j,k));
  43. }
  44. }
  45. }
  46. int n;cin>>n;
  47. for(int i=1;i<=n;i++)
  48. {
  49. cin>>year>>month>>day;
  50. if(g[year-1900][month][day])cout<<"YES\n";
  51. else cout<<"NO\n";
  52. }
  53. return 0;
  54. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注