Calendar Game(记忆化搜索、博弈)

LINK

题目:

在这里插入图片描述

样例:

在这里插入图片描述

翻译:

给出日期(年月日),两个人轮流按照规则操作,首先到达2001年11月4日的人获胜。
规则如下:
1.增加一天
2.增加一个月(到下一个月的当天)
若先手获胜输出YES否则输出NO。

思路:

如果日+1/月+1中有一个为非必胜态,那么当前日期为必胜态;
如果日+1/月+1都是必胜态,那么当前日期为必败态。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
//#define int long long
const int N = 5e3+10;
int mon[20]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int dp[220][20][40];
bool pan(int x){//判断闰年 
	x+=1900;
	if(x%4==0&&x%100!=0||x%400==0)
        return true;
    return false;
}
bool cz(int y,int m,int d){//判断当前日期是否在范围内 
	if(y>2001||y==2001&&m>11||y==2001&&m==11&&d>4)
        return false;
	if(pan(y)&&m==2&&d==29)return true;
	if(mon[m]<d)return false;
	return true;
}
int yy,mm,dd;
int dfs(int y,int m,int d){
	if(dp[y][m][d]!=-1)return dp[y][m][d];
	int flag=1;
	//日+1
	int y2=0;
	if(pan(y)&&m==2)y2=1;//判断闰2月 
	dd=d+1,mm=m,yy=y;
	if(dd>mon[m]+y2){
		dd-=mon[m]+y2;mm++;
	} 
	if(mm>12){
		mm-=12;yy++;
	}
	if(cz(yy,mm,dd)) flag&=dfs(yy,mm,dd);//日+1时为必胜态还是必败态 
	
	//月+1
	yy=y,mm=m+1,dd=d; 
	if(mm>12){
		mm-=12;yy++;
	}
	if(cz(yy,mm,dd))flag&=dfs(yy,mm,dd);//月+1时为必胜态还是必败态 
	
	return dp[y][m][d]=(!flag);//0:必败 1:必胜 
	
}
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int t,n;cin>>t;
	memset(dp,-1,sizeof(dp));
	dp[101][11][4]=1;
	while(t--){
		int y,m,d;cin>>y>>m>>d;
		if(dfs(y-1900,m,d)){
			cout<<"YES"<<endl;
		}else cout<<"NO"<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值