• 1024 Calendar Game


      这是一道关于博弈论的题目,并不是很难,但是由于没有接触过,感觉还是无从下手,下面记录下这道题目。

      (引用别人的)第一个必败状态是2001.11.04。由此可以推出其他任何时间的状态。对于除2001.11.04外的其他任何时间,present状态是由能移动到的下两个next状态决定的(当然有些时间只有一个next状态),比如1924.12.19的状态是由1924.12.20和1925.01.19两个状态决定。如果两个next状态中有一个必败状态,则present状态为必胜状态;如果两个next状态都为必胜状态,则present状态为必败状态。

      下面是代码,代码中的date为第一个必败态,依次推出前面每一天的状态。这个代码是摘自别人的,感觉思路还是比较清晰的,我只是加了一些注释。

      1 #include <iostream>
      2 #include<cstring>  
      3 #include<cstdio>
      4 using namespace std;
      5 struct Date
      6 {
      7     int y,m,d;
      8 }date;
      9 
     10 bool state[102][13][32];//代表着从从1900-1-1到2001-11-4期间每一天是否能必胜,0代表必败,1代表必胜 
     11 bool leapFlag;
     12 int month[]={31,31,28,31,30,31,30,31,31,30,31,30,31};//这里是每一个月的天数,第一个31是为下面mod12做的准备 
     13 
     14 bool is_leapYear(int y)   //是否为闰年
     15 {
     16  return y%4==0 || (y%100 && y%400==0);  
     17 }
     18 
     19 bool getDayBefore()      //获取前一天的日期
     20 {
     21     bool loopFlag=true;
     22     if(date.d>1){date.d--;return loopFlag;}//如果date.d>1,直接减1即可 
     23     if(date.m==3)//当date.d=1时,首先看是否在3月份 
     24     {
     25         date.m--;
     26         if(leapFlag) date.d=29;//如果是闰年 
     27         else date.d=28;
     28     }
     29     else if(date.m==1)//看是否在1月份 
     30     {
     31         date.y--;
     32         date.m=12;
     33         date.d=month[12];
     34         loopFlag=false;
     35     }
     36     else//在其他平常月份 
     37     {
     38         date.m--;
     39         date.d=month[date.m];
     40     }
     41     return loopFlag;
     42 }
     43 
     44 bool isValidNextMonth()  //判断下个月的这天是否有效
     45 {
     46     if((date.y>=101 && ((date.m==10 && date.d>4)||date.m>10))||date.y>101)return false;//如果已经在2001-11-4以后,直接无效 
     47     if(date.d<=month[(date.m+1)%12])return true;  //将month[0]=31 便可用 %12
     48     if(leapFlag && date.m==1 && date.d<30)return true;//如果date.d>month[(date.m+1)%12] 
     49     return false;
     50 }
     51 
     52 void init()//time是date后面的一天,初始情况是date为2001-11-4,time为2001-11-3,依次向前判断每一天是否是必胜态 
     53 {
     54     memset(state,0,102*13*32);//首先置0表示全为必败态 
     55     date.y=101;
     56     date.m=11;
     57     date.d=3;
     58     Date time={101,11,4};
     59     bool loopFlag;
     60     while(date.y>=0)//依次循环,只要在1900年以后就继续循环 
     61     {
     62         leapFlag=is_leapYear(date.y+1900);
     63         loopFlag=true;
     64     //    while(loopFlag)
     65     //    {
     66             if(!state[time.y][time.m][time.d])//如果time为必败态,则date为必胜态 
     67                 state[date.y][date.m][date.d]=true;
     68             else
     69             {
     70                 if(isValidNextMonth())//如果time为必胜态,接着判断下一月的今天是否存在 
     71                 {
     72                     if(date.m==12)
     73                     {
     74                         if(!state[date.y+1][1][date.d])//如果下一月的今天是必败态,则date为必胜态 
     75                           state[date.y][date.m][date.d]=true;
     76                     }
     77                     else if(!state[date.y][date.m+1][date.d])//如果下一月的今天是必败态,则date为必胜态 
     78                           state[date.y][date.m][date.d]=true;
     79                 }
     80             }
     81             time=date;//向前推迟一天 
     82             loopFlag=getDayBefore();//向前推迟一天 
     83         //}
     84     }
     85 }
     86 int main()
     87 {
     88     //freopen("in.txt","r",stdin);
     89     int i,n;
     90     int y,m,d;
     91     cin>>n;
     92     init();
     93     for(i=0;i<n;i++)
     94     {
     95         cin>>y>>m>>d;
     96         if(state[y-1900][m][d])cout<<"YES"<<endl;
     97         else cout<<"NO"<<endl;
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    ORA-01940: cannot drop a user that is currently connected解决方法
    Git基本用法简介
    C 入门 第十节 存储区
    C 入门 第九节 结构体指针
    C 入门 第八节 指针
    C 入门 第七节 结构体
    C 入门 第六节 自定义函数
    C 入门 第五节 多维数组 字符串数组
    C 入门 第四节
    C 入门 第三节
  • 原文地址:https://www.cnblogs.com/wangaohui/p/2867481.html
Copyright © 2020-2023  润新知