poj 1082 Calendar Game 博弈论dp

//poj 1082
//sep9
#include 
using namespace std;
int dp[200][14][33];

int month_day(int y,int m)
{
	if(y%4==0&&y%100!=0||y%400==0)
		if(m==2)
			return 29;
	if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)
		return 31;
	if(m==2)
		return 28;
	return 30;
}


bool valid_day(int y,int m,int d)
{
	if(y>2001)
		return false; 
	if(y<1900)
		return false;
	if(m>12)
		return false;
	if(m<1)
		return false;
	int td=month_day(y,m);
	if(d>td||d<1)
		return false;
	if(y==2001&&y==12)
		return false;
	if(y==2001&&y==11&&d>4)
		return false;
	return true;
}

void next_day(int y,int m,int d,int& ny,int& nm,int& nd)
{
	if(valid_day(y,m,d+1))
		ny=y,nm=m,nd=d+1;
	else if(valid_day(y,m+1,1))
		ny=y,nm=m+1,nd=1;
	else if(valid_day(y+1,1,1))
		ny=y+1,nm=1,nd=1;
	else
		ny=-1;	
}

void next_month(int y,int m,int d,int& ny,int& nm,int &nd)
{
	if(valid_day(y,m+1,d))
		ny=y,nm=m+1,nd=d;
	else if(y==12&&valid_day(y+1,1,d))
		ny=y+1,nm=1,nd=d;
	else 	
		ny=-1;
}

int main()
{
	int cases;
	int ny,nm,nd;
	memset(dp,0,sizeof(dp));
	dp[2001-1900][11][4]=0;
	for(int y=2001;y>=1900;--y)
		for(int m=12;m>=1;--m)
			for(int d=31;d>=1;--d){
				if(!valid_day(y,m,d))
					continue;
				int ny1,nm1,nd1;
				int ny2,nm2,nd2;
				next_day(y,m,d,ny1,nm1,nd1);
				next_month(y,m,d,ny2,nm2,nd2);
				int cnt=0;
				if(ny1 !=-1)	
					if(dp[ny1-1900][nm1][nd1]==0)
						++cnt;
				if(ny2!=-1)
					if(dp[ny2-1900][nm2][nd2]==0)
						++cnt; 
				dp[y-1900][m][d]=cnt>0?1:0;
			}
	scanf("%d",&cases);
	while(cases--){
		int y,m,d;
		scanf("%d%d%d",&y,&m,&d);
		if(dp[y-1900][m][d]>0)
			puts("YES");
		else
			puts("NO");
	}
	return 0;	
} 

你可能感兴趣的:(dp)