uva 1557 - Calendar Game(博弈)

题目链接:uva 1557 - Calendar Game

题目大意:给定一个日期,每次可以选择加一个月,或者加一天,加一个月的前提是下一个月有对应的日期,比如1.30加一个月变成2.30是不合法的,日期上限为2001.11.4。两个人轮流操作,不能操作为失败。

解题思路:dp[y][m][d]表示对应日期是否为先手必胜。预先处理即可,注意细节,包括闰年等。分享代码。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int Y = 105;
const int D = 15;
const int M = 35;
const int month[D] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int dp[Y][D][M];

bool is_year (int y) {
    if (y % 100 == 0 && y % 400 == 0)
        return true;
    if (y % 4 == 0 && y % 100)
        return true;
    return false;
}

int get_day (int y, int m) {
    if (y == 2001 && m == 11)
        return 4;

    if (m == 2 && is_year(y))
        return 29;
    return month[m];
}

bool judge_day (int y, int m, int d) {
    if (y > 101)
        return false;
    if (y == 101 && m > 11)
        return false;
    if (y == 101 && m == 11 && d > 4)
        return false;
    return true;
}

bool getnext_day (int& yy, int& mm, int& dd, int y, int m, int d, int type) {
    if (type) {
        dd = d;
        mm = m + 1;

        if (mm > 12) {
            yy = y + 1;
            mm = 1;
        } else
            yy = y;

        if (dd > get_day(yy + 1900, m))
            return false;

    } else {
        dd = d + 1;

        if (dd > get_day(y + 1900, m)) {
            dd = 1;
            mm = m + 1;
        } else
            mm = m;

        if (mm > 12) {
            yy = y + 1;
            mm = 1;
        } else
            yy = y;
    }
    return judge_day(yy, mm, dd);
}

int SG (int y, int m, int d) {
    if (dp[y][m][d] != -1)
        return dp[y][m][d];

    dp[y][m][d] = 0;
    int yy, mm, dd;

    if (getnext_day(yy, mm, dd, y, m, d, 0)) {
        if (SG(yy, mm, dd) == false)
            dp[y][m][d] = 1;
    }

    if (getnext_day(yy, mm, dd, y, m, d, 1)) {
        if (SG(yy, mm, dd) == false)
            dp[y][m][d] = 1;
    }
    return dp[y][m][d];
}

void init () {
    memset(dp, -1, sizeof(dp));
    dp[101][11][4] = 0;

    for (int i = 0; i <= 101; i++) {
        int limit_month = (i == 101 ? 11 : 12);
        for (int j = 1; j <= limit_month; j++) {
            int limit_day = get_day(1900+i, j);

            for (int d = 1; d <= limit_day; d++)
                SG(i, j, d);
        }
    }
}

int main () {
    init();
    int cas, y, m, d;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%d%d%d", &y, &m, &d);
        printf("%s\n", dp[y-1900][m][d] ? "YES" : "NO");
    }
    return 0;
}

uva 1557 - Calendar Game(博弈),布布扣,bubuko.com

时间: 2024-10-25 23:55:04

uva 1557 - Calendar Game(博弈)的相关文章

UVA 1557 - Calendar Game(博弈dp)

UVA 1557 - Calendar Game 题目链接 题意:给定一个日期,两个人轮流走,每次可以走一月或者一天,问最后谁能走到2001.11.4这个日子 思路:记忆化搜索,对于每个日期,如果下两个状态有一个非必胜态,那么这个状态是必胜态,如果后继状态都是必胜态,那么该状态为必败态 代码: #include <stdio.h> #include <string.h> const int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31,

UVA 10561 - Treblecross(博弈SG函数)

UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',可以在'.'的位置放X,谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败),所以可以以X分为几个子游戏去求SG函数的异或和进行判断,至于求策略,就是枚举每个位置就可以了 代码: #include <stdio.h> #include <string.h> #include <algorithm> usi

UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态 代码: #include <stdio.h> #include <string.h> const int N = 105

UVA 12293 - Box Game(博弈)

UVA 12293 - Box Game 题目链接 题意:两个盒子,一开始一个盒子有n个球,一个只有1个球,每次把球少的盒子中球消掉,把多的拿一些球给这个盒子,最后不能操作的输(球不能少于1个),Alice先手,问谁赢 思路:博弈,题目其实可以转化为,给定一个n,每次把减少1到n/2的数字,最后谁是1谁就输了,那么可以去递推前几项找个规律,或者推理,都可以发现只要是2^i - 1的数字Bob就赢,否则Alice赢 代码: #include <stdio.h> #include <stri

UVA 10891 区间DP+博弈思想

很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态i->j情况下,先手能获得的最大分数.后手能获得的就是sum[i][j]-dp[i][j].接下来枚举先手选取的是两端的哪一段即可. #include <iostream> #include <cstdio> #include <cstring> using name

UVA - 12163 Addition-Subtraction Game (博弈)

Description You and your friend are playing a 2 player game. The game is played in a graph ofV vertices. The vertices are numbered from0 toV-1. The graph has some directed edges. But the graph does not contain any cycles or loops. The rule of the gam

UVA 11892 ENimEN (简单博弈)

题面: 11892  ENimEN In deterministic games no chance is involved, meaning that the final result can be predicted from the initial arrangement assuming players play optimal. These games are so boring.piloop and poopi are professional gamers. They play g

hdu1079 Calendar Game(博弈)

<p style="margin-top: 0px; margin-bottom: 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; ba

Uva 10404-Bachet&#39;s Game(博弈)

题目链接:点击打开链接 在DP专题里刷到的,看着像博弈就水过去了.. 题意:n件物品,两个人轮流取,每次取的数量必须为一个集合s(集合里肯定含有1)里的一个数字,最后不能取者输(即取走最后一件物品者胜). 思路:递推.设 w[i] 为有i件物品时的状态,w[i]=1代表先手必胜,w[i]=0代表先手必败.可以知道w[1]=1,递推生成所有状态. 可以知道对于一个状态,如果他的后继存在必败状态,则该状态为必胜状态:如果该状态的所有后继都为必胜状态,那么该状态为必败状态. #include <alg