分析
- 题意
-
给我们一个日期 y 年、m 月、d 天,
-
我们可以对这个日期进行两个操作,
- 将 这个日期的天数 + 1,形成一个新的日期,
- 将 这个日期的月份 + 1,形成一个新的日期,如果这个不存在 y 年 m+1 月、d 日不存在的话,那么这个操作就不可以进行
-
先在两个极聪明的玩家,轮流进行前面两个操作中的一个,谁先将 所给的日期转移到 2001 年 11 月 4 日及之后的日期之后的的那个玩家获胜,
- 思路
- 本题其实就是一个,就是一个简单的博弈题,只不过 需要特别判断是不是闰年,影响了题目的复杂度,
- 本题的主要的思路就是,从结局的 P/N 状态(后置节点),来逆推 后置节点的父节点,P/N 态,逆推的时候根据:
- 如果当前节点的所有后置节点都是 N 态的话,那么当前节点就是 P 态,
- 如果当前节点的所有后置节点只要有个事 P 态的话,那么当前节点就是 N 态,
- 其实这个逆推的过程像是 dp 求解答案一样,
- 思路是这样但是我们光考虑 平、闰年的时候,判断条件就很复杂了,这个时候我们在 dp 数组的时候有个简化技巧,可以将所有 dp 中的所有元素初始化为 2,为什么是 2?,因为 N 态用 1 表示、P 态用 0 表示,所以用 2,而且我们 dp 的转移方程使用 max 来取最优值的,所以 2 一定不回影响,P、N 态,这样在转移的时候就不用考虑,后置节点所代表的那一天存在不存在,即使不存在也不影响,状态转移方程的取值,,
- 剩下的直接看代码把。。。
代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <bitset>
#include <vector>
#include <stack>
#include <map>
/* #include <unordered_map> */
#include <sstream>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair<int, int>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
using namespace std;
int mon[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int dp[2005][15][35];
int main()
{
/* fre(); */
fill(dp[0][0], dp[0][0] + 2005*15*35, 2);
dp[2001][11][4] = 0;
dp[2001][11][3] = 1;
dp[2001][11][2] = 0;
dp[2001][11][1] = 1;
for(int y = 2001; y >= 1900; y --)
{
if(y == 2001)
{
if((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) mon[2] ++;
for(int m = 10; m >= 1; m --)
{
for(int d = mon[m]; d >= 1; d --)
{
int td = d + 1, tm = m, ty = y;
if(td > mon[m]) td = 1, tm ++;
if(tm > 12) tm = 1, ty ++;
int tdd = d, tmm = m + 1, tyy = y;
if(tmm > 12) tmm = 1, tyy ++;
dp[y][m][d] = min(dp[ty][tm][td], dp[tyy][tmm][tdd]);
dp[y][m][d] ^= 1;
}
}
if((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) mon[2] --;
}
else
{
if((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) mon[2] ++;
for(int m = 12; m >= 1; m --)
{
for(int d = mon[m]; d >= 1; d --)
{
int td = d + 1, tm = m, ty = y;
if(td > mon[m]) td = 1, tm ++;
if(tm > 12) tm = 1, ty ++;
int tdd = d, tmm = m + 1, tyy = y;
if(tmm > 12) tmm = 1, tyy ++;
dp[y][m][d] = min(dp[ty][tm][td], dp[tyy][tmm][tdd]);
dp[y][m][d] ^= 1;
}
}
if((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) mon[2] --;
}
}
int T; sd(T);
while(T --)
{
int y, m, d;
sc("%d %d %d", &y, &m, &d);
if(dp[y][m][d])
pr("YES\n");
else
pr("NO\n");
}
return 0;
}