POJ 1082 Calendar Game (博弈)

题意:甲与乙做一个游戏,给定一个1991/1/1至2001/11/4号之间的一个日期,看谁能最终到达2001/11/4。有两种移动方式,1.移动到下一天;2.移动到下一个月的同一天(若下一个月的该天不存在,则不能移动)
题解:如果一个状态的后继状态都是必胜状态,那么它是必败状态。如果一个状态的后继状态中存在必败状态,那么它是必胜状态。
PS:感觉好奇怪,递归时倘若我先处理下一天,再处理下一月,结果便是错误的。真奇怪····有知道的麻烦告知下。

#include<iostream>
#include<cstring>
using namespace std;

int dp[105][13][32];
int end[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

bool leap ( int y )
{
    return y % 400 == 0 || ( y % 4 == 0 && y % 100 != 0 );
}

int solve ( int y, int m, int d )
{
    if ( y>101 || (y==101 && m>11) || (y==101 && m==11 && d>4) )
        return 1;
    if ( dp[y][m][d] != -1 )
        return dp[y][m][d];

    int f1 = 1, f2 = 1;

    if ( m == 12 )  //移动到下一个月
        f1 = solve ( y+1, 1, d );
    else
    {
        if ( d <= end[m+1] )
            f1 = solve ( y, m+1, d );
        else if ( m == 1 && d == 29 && leap(y+1900) )
            f1 = solve ( y, m+1, d );
    }

    if ( d == end[m] ) //移动到下一天
    {
        if ( m == 12 )
            f2 = solve ( y+1, 1, 1 );
        else if ( m == 2 && leap(y+1900) )
            f2 = solve ( y, m, 29 );
        else
            f2 = solve ( y, m+1, 1 );
    }
    else f2 = solve ( y, m, d+1 );

    dp[y][m][d] = (!f1 || !f2);
    return dp[y][m][d];
}


int main()
{
    int t, year, month, day;
    cin >> t;
    memset(dp,-1,sizeof(dp));
    dp[101][11][4] = 0;
    solve ( 0, 1, 1 );
    while(t--)
    {
        cin >> year >> month >> day;
        if ( dp[year-1900][month][day] )
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值