Calendar Game HDU - 1079 博弈论打表

题意

  • 给定一个包含年月日的日期,每次移动只能向未来移动一天或者一个月,若无法移动一个月(如1月31日移动2月份),那就不进行这次操作。
  • 由于数据给定的从1900年至2001年,只有100年的天数,上限不超过四万个天数,可以先预处理打表后 O ( 1 ) O(1) O(1) 查询得到,或者在线处理然后套个记忆化搜索,类似于 d p dp dp ,代码如下,采用记忆化搜索进行解决。
  • 在代码当中,定义先手必胜 N N N 点的 s g sg sg 值为1,另外先手必败的 P P P 点为 -1。在博弈论当中,如果一个状态走到下一个状态的路径中存在 P P P 点,则该点的状态必定是 N N N 点;反之若下一个状态不存在 P P P 点,则这个状态为 P P P 点。
  • 其中在进行下一天或者下一个月超出目标范围的时候,返回1的原因如上,因为下一步无法到达目标日期,所以该点状态应该先手必败,所以下一个状态中标记为1便是让原本状态必败。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uii;
typedef pair<int, ll> pii;
template<typename T>
inline void rd(T& x)
{
    
    
	int tmp = 1; char c = getchar(); x = 0;
	while (c > '9' || c < '0') {
    
     if (c == '-')tmp = -1; c = getchar(); }
	while (c >= '0' && c <= '9') {
    
     x = x * 10 + c - '0'; c = getchar(); }
	x *= tmp;
}
const int N = 2e5 + 10;
const int M = 1e7 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int n, m, k;
int sg[2005][15][35] = {
    
     0 };
int day[13] = {
    
     0,31,28,31,30,31,30,31,31,30,31,30,31 };
inline bool isLeap(int y) {
    
    
	return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
int dfs(int y, int m, int d) {
    
    
	if (sg[y][m][d]) return sg[y][m][d];
	if (y > 2001) return 1;
	if (y == 2001 && m > 11) return 1;
	if (y == 2001 && m == 11 && d > 4) return 1;
	//+1天
	if (m == 2) {
    
    
		if (isLeap(y) && d == 29 || !isLeap(y) && d == 28) {
    
    
			if (dfs(y, m + 1, 1) == -1) return sg[y][m][d] = 1;
		}
		else {
    
    
			if (dfs(y, m, d + 1) == -1) return sg[y][m][d] = 1;
		}
	}
	else if (d == day[m]) {
    
    
		if (m < 12 && dfs(y, m + 1, 1) == -1) return sg[y][m][d] = 1;
		else if (m == 12 && dfs(y + 1, 1, 1) == -1) return sg[y][m][d] = 1;
	}
	else {
    
    
		if (dfs(y, m, d + 1) == -1) return sg[y][m][d] = 1;
	}

	//+1个月
	if (m != 12) {
    
    
		if (day[m + 1] >= (d + isLeap(y) && m == 2)) {
    
    
			if (dfs(y, m + 1, d) == -1) return sg[y][m][d] = 1;
		}
	}
	else {
    
    
		if (dfs(y + 1, 1, d) == -1) return sg[y][m][d] = 1;
	}
	return sg[y][m][d] = -1;
}
int main() {
    
    
#ifdef _DEBUG
	FILE* _INPUT = freopen("input.txt", "r", stdin);
	//	FILE* _OUTPUT = freopen("output.txt", "w", stdout);
#endif // !_DEBUG
	int cas = 0, T = 0;
	rd(T);
	sg[2001][11][4] = -1;
	while (T--) {
    
    
		//	while (~scanf("%d %d", &n,&k)) {
    
    
		int y, m, d; rd(y), rd(m), rd(d);
		if (dfs(y, m, d) == 1) puts("YES");
		else puts("NO");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bloom_er/article/details/113774668