伊甸园日历游戏

描述 Description  

         Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来。然后他们轮流对这个日期进行操作:

  1 : 把日期的天数加1,例如1900.1.1变到1900.1.2

  2 : 把月份加1,例如:1900.1.1变到1900.2.1

  其中如果天数超过应有天数则日期变更到下个月的第1天。月份超过12则变到下一年的1月。而且进行操作二的时候,如果有这样的日期:1900.1.31,则变成了1900.2.31,这样的操作是非法的,我们不允许这样做。而且所有的操作均要考虑历法和闰年的规定。

  谁先将日期变到2001.11.4谁就赢了。

  每次游戏都是Adam先操作,问他有没有必胜策略?

输入格式 Input Format

        一个测试点。多组数据。

 第一行为数据组数。

 接下来一行X Y Z表示X年Y月Z日

输出格式 Output Format    

        输出“YES”or“NO”表示亚当是否有必胜策略。

逆推,DP

#include<iostream>
using namespace std;

int t,year,month,day; 
int f[2012][20][40]={0}; 
int tool[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 

void Dp(){
     int y=2001,m=11,d=4;
     f[2001][11][4]=1; 
     while(!(y==1900&&m==1&&d==1))
     {
       int y1=y,m1=m,d1=d; 
       d--;
       if(d==0)
       {
         m--;
         if(m==0)
         {
           m=12;
           y--;   
                 } 
         d=tool[m];
         if(((y%4==0&&y%100!=0)||y%400==0)&&m==2) d+=1; 
               } 
       if(f[y1][m1][d1]==1)
       {f[y][m][d]=2;continue;}
       
       y1=y;m1=m;d1=d;
       
       m1++;
       if(m1==13)
       {
         y1++;
         m1=1;    
                }
       
       if(f[y1][m1][d1]==1)
       f[y][m][d]=2;
       else f[y][m][d]=1;          
                                  } 
     } 

int main()
{
    Dp(); 
    cin>>t;
    
    while(t>0)
    {
      t--; 
      cin>>year>>month>>day;
      if(f[year][month][day]==2) cout<<"YES"<<endl;
      else cout<<"NO"<<endl; 
              } 
    return 0; 

    } 
原文地址:https://www.cnblogs.com/noip/p/2623322.html