[POJ1082]Calendar Game

题目大意:
  日历上博弈,从给定的日期,按照下述规则跳转日期:
    1.跳到第二天;
    2.调到下个月相同的日期(如果没有就不能跳转)。
  刚刚好跳到2001年11月4日的人胜,跳转时不能跳到2001年11月4日以后。
  现在A和B轮流跳,问A是否有必胜策略。

思路:
  如果不考虑边界情况,每一个对应的日期都有两个直接相连的后继状态,也同时是两个日期直接相连的后继状态。
  这样,所有的状态构成一个DAG,我们可以在DAG上进行DP。
  一个状态是必败状态当且仅当它的两个前驱状态都是必胜状态。
  一个状态是必胜状态当且仅当它的其中一个前驱状态是必败状态。
  我们可以先预处理出所有日期所对应的状态,然后回答即可。
  另外本题也有找规律的做法,设月份为m,日期为d。
  则当m+d为偶数时必胜,当m+d为奇数时必败。
  特别地,当m=9或11且d=30时,也为必胜状态。

  1 #include<map>
  2 #include<cstdio>
  3 #include<cctype>
  4 inline int getint() {
  5     register char ch;
  6     while(!isdigit(ch=getchar()));
  7     register int x=ch^'0';
  8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  9     return x;
 10 }
 11 struct Date {
 12     int y,m,d;
 13     bool operator < (const Date &another) const {
 14         if(y<another.y) {
 15             return true;
 16         } else if(y==another.y){
 17             if(m<another.m) {
 18                 return true;
 19             } else if(m==another.m) {
 20                 if(d<another.d) return true;
 21             }
 22         }
 23         return false;
 24     }
 25     bool operator <= (const Date &another) const {
 26         if(y<another.y) {
 27             return true;
 28         } else if(y==another.y){
 29             if(m<another.m) {
 30                 return true;
 31             } else if(m==another.m) {
 32                 if(d<=another.d) return true;
 33             }
 34         }
 35         return false;
 36     }
 37     bool isleap() const {
 38         return (!(y%4)&&(y%100))||!(y%400);
 39     }
 40     int day() const {
 41         if(m==1||m==3||m==5||m==7||m==8||m==10||m==12) return 31;
 42         if(m==4||m==6||m==9||m==11) return 30;
 43         return isleap()?29:28;
 44     }
 45     Date decday() const {
 46         Date ret=*this;
 47         ret.d--;
 48         if(!ret.d) {
 49             ret.m--;
 50             if(!ret.m) {
 51                 ret.y--;
 52                 ret.m=12;
 53             }
 54             ret.d=ret.day();
 55         }
 56         return ret;
 57     }
 58     Date decmonth() const {
 59         Date ret=*this;
 60         ret.m--;
 61         if(!ret.m) {
 62             ret.y--;
 63             ret.m=12;
 64         }
 65         if(ret.d>ret.day()) return (Date){1899,12,31};
 66         return ret;
 67     }
 68     Date incday() const {
 69         Date ret=*this;
 70         ret.d++;
 71         if(ret.d>ret.day()) {
 72             ret.m++;
 73             if(ret.m==13) {
 74                 ret.y++;
 75                 ret.m=1;
 76             }
 77             ret.d=1;
 78         }
 79         return ret;
 80     }
 81     Date incmonth() const {
 82         Date ret=*this;
 83         ret.m++;
 84         if(ret.m==13) {
 85             ret.y++;
 86             ret.m=1;
 87         }
 88         if(ret.d>ret.day()) return (Date){2001,11,5};
 89         return ret;
 90     }
 91 };
 92 const Date begin=(Date){1900,1,1},end=(Date){2001,11,4};
 93 std::map<Date,bool> m;
 94 inline void dp() {
 95     for(Date d=end;begin<=d;d=d.decday()) {
 96         if(d.incday()<=end) {
 97             m[d]|=!m[d.incday()];
 98         }
 99         if(d.incmonth()<=end) {
100             m[d]|=!m[d.incmonth()];
101         }
102     }
103 }
104 inline bool query(const int &y,const int &mm,const int &d) {
105     return m[(Date){y,mm,d}];
106 }
107 int main() {
108     dp();
109     for(register int n=getint();n;n--) {
110         const int &y=getint(),&m=getint(),&d=getint();
111         puts(query(y,m,d)?"YES":"NO");
112     }
113     return 0;
114 } 

 

posted @ 2017-09-26 15:45  skylee03  阅读(144)  评论(0编辑  收藏  举报