HDU 1079 Calendar Game 简单博弈

题目大意:

就是现在两个人在玩一个日历, 初始选定一个起点日期然后两人轮流操作, 每次可以选择跳到下一天或者下一个月对应的同一天, 但是当下一个月没有这一天是不能选择跳到下一个月

比如1月31不能跳到2月31, 因为没有

那么到达2001年11月4日的人胜利, 游戏过程中如果谁超出这个日期就输了, 初始位置选定在1900年1月1日到2001年11月4日之间, 问先手是否会胜利是就Yes否则No


大致思路:

就是一个非常简单的NP点的问题, 就是换成在日期上转移而已, 将非法日期都视为N点, 与处理处所有的日子的NP值即可, 当起点是P点时先手败否则胜

没什么难度= =


代码如下:

Result  :  Accepted     Memory  :  1660 KB     Time  :  0 ms

/*
 * Author: Gatevin
 * Created Time:  2015/4/28 19:40:43
 * File Name: Rin_Tohsaka.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
#define foreach(e, x) for(__typeof(x.begin()) e = x.begin(); e != x.end(); ++e)
#define SHOW_MEMORY(x) cout<<sizeof(x)/(1024*1024.)<<"MB"<<endl

#define base 1900

bool np[110][13][32];
int Days[13] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool leap(int year)
{
    if(year % 100 == 0)
    {
        if(year % 400 == 0) return true;
        return false;
    }
    if(year % 4 == 0) return true;
    return false;
}

bool right(int year, int month, int day)//判断是否日期合法
{
    if(year == 2001)
    {
        if(month > 11) return false;
        if(month == 11 && day >= 4) return false;
    }//超出终点了
    if(year < 1900) return false;//小于起点
    if(leap(year) && month == 2 && day == 29)//闰年的2月29
        return true;
    if(day > Days[month]) return false;
    return true;
}

bool nextday(int year, int month, int day)//注意非法日期的np都是0
{
    if(leap(year))
    {
        if(month == 2 && day == 29)
            return np[year - base][3][1];
        if(month == 2 && day == 28)
            return np[year - base][2][29];
    }
    if(month == 12 && day == 31)
        return np[year + 1 - base][1][1];
    if(day + 1 > Days[month])
        return np[year - base][month + 1][1];
    return np[year - base][month][day + 1];
}

bool nextmonth(int year, int month, int day)//非法日期的np值都是0
{
    if(month == 12)
        return np[year + 1 - base][1][day];
    return np[year - base][month + 1][day];
}

int main()
{
    memset(np, 0, sizeof(np));
    np[2001 - base][11][4] = 1;//=1表示为P点, 0表示是N点
    
    for(int i = 2001; i >= 1900; i--)
        for(int j = 12; j >= 1; j--)
            for(int k = 31; k >= 1; k--)
            {
                if(!right(i, j, k)) continue;
                bool p = nextday(i, j, k) || nextmonth(i, j, k);//有没有可到P点的路
                if(p) np[i - base][j][k] = 0;
                else np[i - base][j][k] = 1;
            }
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int year, month, day;
        scanf("%d %d %d", &year, &month, &day);
        if(np[year - base][month][day])
            printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}


你可能感兴趣的:(calendar,game,HDU,1079,简单博弈)