POJ 1082 (博弈)

題意:從一個日期開始,兩個人輪流選擇日期,可以選擇上一個人所選日期的後一天,也可以選擇下一個月的這天。

思路:從目標日期開始求出所有的sg值。判斷sg值是否爲0


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <string>
#define LL long long
#define DB double
#define SF scanf
#define PF printf
#define N 2009
#define bug cout<<"bug"<<endl;
using namespace std;
int dp[N][14][33];
bool run(int y)
{
    if(y%400==0) return 1;
    if(y%100==0) return 0;
    return (y%4)==0;
}
bool ok(int y,int m,int d)
{
    if(m==2)
    {
        if(run(y))
        {
            return d<=29;
        }else
        {
            return d<=28;
        }
    }
    if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)
    {
        return d<=31;
    }else
    {
        return d<=30;
    }
}
int fin1(int y,int m,int d)
{
    if(m<12)
    return dp[y][m+1][d];
    else
    return dp[y+1][1][d];
}
int fin2(int y,int m,int d)
{
    if(m==12&&d==31)
    return dp[y+1][1][1];
    if(dp[y][m][d+1]==-1)
    return dp[y][m+1][1];
    return dp[y][m][d+1];
}
void init()
{
    memset(dp,-1,sizeof(dp));
    for(int y=2001;y>=1900;y--)
    for(int m=12;m>0;m--)
    for(int d=31;d>0;d--)
    {
        if(!ok(y,m,d)) continue;
        int t1 = fin1(y,m,d);
        int t2 = fin2(y,m,d);
        if(t1!=0&&t2!=0) dp[y][m][d] = 0;
        else if(t1!=1&&t2!=1) dp[y][m][d] = 1;
        else if(t1!=2&&t2!=2) dp[y][m][d] = 2;
        else dp[y][m][d] = 3;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    init();
    int cas,y,m,d;SF("%d",&cas);
    while(cas--)
    {
        SF("%d%d%d",&y,&m,&d);
        PF("%s",dp[y][m][d]!=0?"YES\n":"NO\n");
    }
    return 0;
}


發佈了230 篇原創文章 · 獲贊 3 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章