hdu 1079 Calendar Game(博弈SG函数 || 奇偶找规律)
2012-09-05 21:56
274 查看
题意:
从当前日期,在他/她转的玩家可以移动到下一个历日或下月的同一天。当在之后的一个月中没有在同一天,播放器只能移动到下一个的日历日期。例如,从1924年12月19日,你可以移动到1924年12月20日,下一个日期,或一月19日,1925年,在同一天在下个月。然而,2001年1月31日,你可以只移动2001年2月1日,因为2001年2月31日是无效的。一个球员赢得比赛时,他/她到底到达的日期2001年11月4日。如果一个玩家移动到日期2001年11月4号之后,他/她输了比赛。
思路:
(2001 , 11 , 4)是个必败点,能到(2001, 11 , 4)的是必胜点,由时间从后向前推。
最后若输入的sg[] = 0即为必败点,输出 NO
代码:
找规律,不管是月份加一,还是日期加一,都改变了奇偶性,只有两个特殊日期9月30日,和11月30日例外(不管该年是否为润年,2月28\ 29同样一步都会发生正常奇偶变化)。
那么目标日期是11月4日,为奇数。初始日期如果为偶数的话,先者必胜。
考虑特殊是日期,两个特殊日期本来为奇数,可以做到移动一步还是奇数,那么必胜点与必败点发生变化。
那么会不会在中途经过这两个日期呢。
如果本来为偶数,如果经过特殊日期就会改变奇偶,从必胜到必败。作为先手,不会主动进入特殊日期,而后者不可能从奇数依旧到达特殊日期的奇数。
如果本来为奇数,同样先手想赢,但是不可能进入特殊日期。保持奇偶性交替变化。
这样一来只可能是初始为特殊日期,否则中途不可能出现特殊日期
代码:
从当前日期,在他/她转的玩家可以移动到下一个历日或下月的同一天。当在之后的一个月中没有在同一天,播放器只能移动到下一个的日历日期。例如,从1924年12月19日,你可以移动到1924年12月20日,下一个日期,或一月19日,1925年,在同一天在下个月。然而,2001年1月31日,你可以只移动2001年2月1日,因为2001年2月31日是无效的。一个球员赢得比赛时,他/她到底到达的日期2001年11月4日。如果一个玩家移动到日期2001年11月4号之后,他/她输了比赛。
思路:
(2001 , 11 , 4)是个必败点,能到(2001, 11 , 4)的是必胜点,由时间从后向前推。
最后若输入的sg[] = 0即为必败点,输出 NO
代码:
#include<iostream> #include<string.h> using namespace std; int sg[500][20][40]; int day[400]; int mm[15]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int g(int y , int m , int d) { if(sg[y][m][d]!=-1) return sg[y][m][d]; int flag=0; if(y>101) return sg[y][m][d]=0; if(m==2 && d==day[y] || m<12 && mm[m]==d && mm[m+1]>=d) { int a=g(y,m+1,d) , b=g(y,m+1,1); if(a==0 || b==0) return sg[y][m][d]=1; else if(a && b) return sg[y][m][d]=0; } else if(m<12 && mm[m]==d && mm[m+1]<d) { int a=g(y,m+1,1); if(a==0) return sg[y][m][d]=1; else return sg[y][m][d]=0; } else if(m==2 && d<day[y] || m<12 && d<mm[m] || m==12 && d<mm[12]) { //cout<<"**************"<<endl; int a=g(y,m,d+1) , b=g(y , m+1 , d);// cout<<"a= "<<a<<" b= "<<b<<endl; if(a==0 || b==0 ) return sg[y][m][d]=1; else if(a && b) return sg[y][m][d]=0; } else if(m==12 && d==mm[12]) { int a=g(y+1 ,1 ,1) , b=g(y+1 ,1, d); if(a==0 || b==0) return sg[y][m][d]=1; else if(a && b) return sg[y][m][d]=0; } } int main() { int y,m,d; int t; memset(sg,-1,sizeof(sg)); for(int i=1900;i<=2001;i++) if(i%4==0&&i%100!=0 || i%400==0) day[i-1900+1]=29; else day[i-1900+1]=28; sg[101][11][4]=0; for(int i=5;i<=mm[11];i++) sg[101][11][i]=1; for(int i=1;i<=mm[12];i++) sg[101][12][i]=1; scanf("%d",&t); while(t--) { scanf("%d%d%d",&y,&m,&d); y-=1900; g(y,m,d);// cout<<"**= "<<sg[101][11][4]<<" "<<sg[101][11][3]<<endl; if(sg[y][m][d]==1) printf("YES\n"); else printf("NO\n"); } return 0; }
找规律,不管是月份加一,还是日期加一,都改变了奇偶性,只有两个特殊日期9月30日,和11月30日例外(不管该年是否为润年,2月28\ 29同样一步都会发生正常奇偶变化)。
那么目标日期是11月4日,为奇数。初始日期如果为偶数的话,先者必胜。
考虑特殊是日期,两个特殊日期本来为奇数,可以做到移动一步还是奇数,那么必胜点与必败点发生变化。
那么会不会在中途经过这两个日期呢。
如果本来为偶数,如果经过特殊日期就会改变奇偶,从必胜到必败。作为先手,不会主动进入特殊日期,而后者不可能从奇数依旧到达特殊日期的奇数。
如果本来为奇数,同样先手想赢,但是不可能进入特殊日期。保持奇偶性交替变化。
这样一来只可能是初始为特殊日期,否则中途不可能出现特殊日期
代码:
#include<iostream> #include<string.h> using namespace std; int main() { int y,m,d , t; scanf("%d",&t); while(t--) { scanf("%d%d%d",&y,&m,&d); if((m+d)%2==0 || m==9 && d==30 || m==11 && d==30) printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- HDU 1079 Calendar Game (奇偶规律,SG函数)*
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- hdu 1079 Calendar Game (SG函数)(博弈——找规律)
- HDU 1079 Calendar Game(博弈,找规律可解)
- HDU 1079 Calendar Game (博弈 sg函数)
- HDU-1079 Calendar Game(找规律,博弈)
- hdu 1079 Calendar Game 找规律+SG函数两种方法 算不上今天的首A