题意:给定一个日期,两个人轮流走,每次可以走一月或者一天,问最后谁能走到2001.11.4这个日子
思路:记忆化搜索,对于每个日期,如果下两个状态有一个非必胜态,那么这个状态是必胜态,如果后继状态都是必胜态,那么该状态为必败态
代码:
#include <stdio.h> #include <string.h> const int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int dp[105][15][32]; int t, y, m, d; bool islead(int num) { num += 1900; if (num % 100 == 0) { if (num % 400 == 0) return true; } else { if (num % 4 == 0) return true; } return false; } bool judge(int y, int m, int d) { if (y >= 2001) { if (y > 2001) return false; if (m >= 11) { if (m > 11) return false; if (d > 4) return false; } } if (islead(y) && m == 2 && d == 29) return true; if (day[m] < d) return false; return true; } int dfs(int y, int m, int d) { if (dp[y][m][d] != -1) return dp[y][m][d]; if (y == 101 && m == 11 && d == 4) return dp[y][m][d] = 1; int dd = d, mm = m + 1, yy = y; if (mm > 12) { mm -= 12; yy++; } int ans = 1; if (judge(yy, mm, dd)) ans &= dfs(yy, mm, dd); int tmp = 0; if (islead(y) && m == 2) tmp = 1; dd = (d + 1); mm = m; yy = y; if (dd > day[m] + tmp) { dd -= day[m] + tmp; mm++; } if (mm > 12) { yy++; mm -= 12; } if (judge(yy, mm, dd)) ans &= dfs(yy, mm, dd); return dp[y][m][d] = (!ans); } int main() { memset(dp, -1, sizeof(dp)); scanf("%d", &t); while (t--) { scanf("%d%d%d", &y, &m, &d); y -= 1900; printf("%s\n", dfs(y, m, d)?"YES":"NO"); } return 0; }
UVA 1557 - Calendar Game(博弈dp),布布扣,bubuko.com
UVA 1557 - Calendar Game(博弈dp)
原文:http://blog.csdn.net/accelerator_/article/details/37886049