【题解】LuoGu1512:伊甸园日历游戏

原题传送门
dp
d p i , j , k dp_{i,j,k} 表示 i j k i年j月k日 是否必胜

  • d p i , j , k = d p i , j , k + 1 dp_{i,j,k}|=dp_{i,j,k+1}
  • d p i , j , k = d p i , j + 1 , k dp_{i,j,k}|=dp_{i,j+1,k}

判断一下日期合理性就好了

Code:

#include <bits/stdc++.h>
#define maxn 2020
using namespace std;
int dp[maxn][20][40], year, month, date;

bool check(int i, int j, int k){
	if (i > 2006 || j > 12 || k > 31 || j < 1 || k < 1) return 0;
	if (i >= 2006 && j >= 11 && k >= 4) return 0;
	if (j == 1 || j == 3 || j == 5 || j == 7 || j == 8 || j == 10 || j == 12) return k <= 31;
	if (j == 4 || j == 6 || j == 9 || j == 11) return k <= 30;
	if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0) return k <= 29; else return k <= 28;
}

int main(){
//	freopen("calendar.in", "r", stdin);
//	freopen("calendar.out", "w", stdout);
//	printf("%d\n", check(1904, 4, 31));
	dp[2006][11][3] = 1;
	for (int i = 2006; i >= 1900; --i)
		for (int j = 12; j; --j)
			for (int k = 31; k; --k)
				if (check(i, j, k)){
					int nxti = i, nxtj = j + 1, nxtk = k;
					if (nxtj > 12) ++nxti, nxtj = 1;
					if (check(nxti, nxtj, nxtk)) dp[i][j][k] |= dp[nxti][nxtj][nxtk] == 0;
				//	if (i == 2012 && j == 11 && k == 22) printf("%d %d %d\n", nxti, nxtj, nxtk);
					nxti = i, nxtj = j, nxtk = k + 1;
					if (!check(nxti, nxtj, nxtk)) ++nxtj, nxtk = 1;
					if (nxtj > 12) ++nxti, nxtj = 1;
					if (check(nxti, nxtj, nxtk)) dp[i][j][k] |= dp[nxti][nxtj][nxtk] == 0;
				}
/*	int flag = 0;
	for (int i = 1900; i <= 1999; ++i)
		for (int j = 1; j <= 12; ++j)
			for (int k = 1; k <= 31; ++k)
				if (check(i, j, k) && !dp[i][j][k]) flag++;
	printf("%d\n", flag);*/
	int M; scanf("%d", &M);
	while (M--){
		scanf("%d%d%d", &year, &month, &date);	
		if (dp[year][month][date]) puts("YES"); else puts("NO");
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/108197633