【NOIP模拟题】日历游戏
2016-01-28 12:42
423 查看
题意
双人博弈。给定初始日期(在1900年1月1日后),每次两种操作:
①变成下一天;
②变成下个月的这一天。
谁先变到2012年12月22日谁赢。
分析
博弈问题,要么直接找规律,要么记忆化搜索或者递推。这题应该没有直接的规律,又由于1900年到1月1日到2012年12月22日中间的日子不多,所以考虑直接记忆化搜索。
没啥好讲的,注意来自幼儿园的各种细节,特别是多组询问。
代码
#include <cstdio> #include <map> using namespace std; int a,b,c; map<int,int> mp; inline int lastday(int y,int m) { if (m==1||m==3||m==5||m==7||m==8||m==10||m==12) return 31; if (m==4||m==6||m==9||m==11) return 30; if (m==2) return 28+(y%4==0&&y%100!=0); } inline void nextday(int &y,int &m,int &d) { d++; if (d>lastday(y,m)) d=1,m++; if (m>12) m=1,y++; } inline void preday(int &y,int &m,int &d) { d--; if (d<1) { m--; if (m<1) y--,m=12; d=lastday(y,m); } } inline void nextmonth(int &y,int &m,int &d) { m++; if (m>12) m=1,y++; } inline void premonth(int &y,int &m,int &d) { m--; if (m<0) m=12,y--; } inline int legal(int y,int m,int d) { return 0<d&&d<=lastday(y,m); } inline int get(int y,int m,int d) { return y*128*32+m*32+d; } int dfs(int y,int m,int d) { if (y>2012) return 1; if (y==2012&&m>12) return 1; if (y==2012&&m==12&&d>22) return 1; if (y==2012&&m==12&&d==22) return -1; if (mp[get(y,m,d)]) return mp[get(y,m,d)]; int state=0; nextday(y,m,d); state=-dfs(y,m,d); preday(y,m,d); if (state==-1) { nextmonth(y,m,d); if (legal(y,m,d)) state=-dfs(y,m,d); premonth(y,m,d); } return mp[get(y,m,d)]=state; } int main(void) { for (;~scanf("%d%d%d",&a,&b,&c);) printf("%s\n",dfs(a,b,c)>0?"YES":"NO"); return 0; }
相关文章推荐
- [LeetCode] Patching Array 补丁数组
- 网络爬虫介绍(待完善)
- QTextEdit实现语法高亮-Syntax Highlighter Example例子简单介绍
- hdu 1024 Max Sum Plus Plus(动态规划+m子段和的最大值)
- crc32校验48位mac 地址
- linux内核启动流程分析
- [解析苹果官方文档]之[UIView Class Reference]
- 数组
- 测试设计中需要考虑的22种测试类型
- 二叉排序树(创建,查找,删除)
- js定时执行
- Centos 6.5 安装FTP服务
- MonogoDb的角色分类
- 【Win 10应用开发】响应系统回退键的导航事件
- 【转】Objective-C消息机制的原理
- PHP实现过滤各种HTML标签
- iOS 动态改变cell的高度
- Hibernate各种主键生成器策略与配置详解(转载)
- iOS开发之UILabel动态高度设置方法
- 伸展树学习小结