zoukankan      html  css  js  c++  java
  • HDU 1079 Calendar Game (博弈或暴搜)

    题意:给定一个日期,然后 A 和 B 双方进行操作,谁先把日期变成2001年11月04日,将获胜,如果超过该日期,则输了,就两种操作。

    第一种:变成下一天,比如现在是2001.11.3 变成 2001.11.4

    第二种,变成下一个月的同一天,比如现在是2001.10.3 变成 2001.11.3,当然有可能是不成立的,比如2001.1.30 不能变成2001.2.30,因为2月没有30天。

    析:因为题目中说了是从1990年到2001年,大约100年的时间,也就是400 * 100,完全可以存储下来,或者是直接暴力并且记忆化,这里就是要处理一些特殊情况,比如闰年,下一天跨年了,或者超过2001.11.4了等等,速度还挺快的。

    这第二种解法才是正规的解法,要发现这两种情况的共同点,首先把月份和日份看成一个整体,或者是求和sum就好,因为 11+4 = 15,15 是奇数,那么如果开始的日期是偶数,就一定能够获胜,除非有一种日期从能偶数只能变成偶数,很遗憾,并没有这种日期,也就是只要日期是偶数就是一定能够获胜,下面有解释,当然前提是这两个人都足够聪明,那么是不是是奇数就不能胜了?答案不一定,下面慢慢分析,把日期分成三大类,

    第一类,变成一个月的同一天,那么如果能变化的话,sum的奇偶性会发生变化,也就是奇变偶,偶变奇

    第二类,就成下一天,对于这个仔细点会发现,sum不全是会变化,只有几个是特例,这第二类就是sum会变化的,

    第三类,我们细分一下哪几个特例,也就是说下一天,sum不一定会发生变化的,首先就是 2 月 这个特殊的月份,先考虑不是闰年,那么 2 月就只有 28 天,2 + 28 是偶数,我们推理过如果 sum 是偶数,那么就一定能获胜,那么如果是闰年呢,那么 2 月有 29 天,那么是一个奇数,它的一天是 3.1,奇偶性变成了变化,所以不用考虑 2 月了,同理可以解决 4.30 虽然下一个日期是 5.1 也是偶数,但是它本身偶数,所以一定能获胜,6.30 也是,但是有两个特例也就满足这第三类的,9.30 和 11.30 这两个 sum 是奇数,但是它的下一天是是奇数,下一个月是偶数,也就是说奇偶性不一定不发生变化。但是这两个日期一定能获胜,为什么呢,因为当某个玩家到了 9.30 或者是 11.30 ,我们前面考虑过了如果日期是偶数,就能够获胜,所以它肯定是选择变成下一个日期,这样的话,对方就是奇数了,而下次我就是成偶数了。也就是说如果经过 9.30 或者是 11.30 那么奇偶就会发生翻转。那么这和我们前面说的偶数就一定能够获胜好像是矛盾啊,其实不然,因为每个人都是足够聪明的,能够获胜的那个玩家肯定要避免对方能够拿到这个日期,而且完全可以做到举个例子,  9.30 能够到达 9.30 的只有 9.29 或者是 8.30,那么只要 9.29 的变成下一个月,8.30 的变成下一天,就能够避免对方得到这两个日期,也就能够获胜了。同时如果给定一开始给定的就是 9.30 或 11.30 ,那么这个和虽然不是偶数,也是也能获胜,至少为什么,前面已经说了,经过这两个日期,聪明的玩家的可以把奇偶性翻转,并且以后可以避免让对方再得到这两个日期。

    综上,如果先手想胜的话,只有二种情况,一种是日份和月份的和是偶数,第二种,就是开始日期就是 9.30 或者是 11.30。

    两种不同的解法,代码差的可不是一点,但是思维量也不是同等的

    代码如下:

    首先先贴上 dfs 记忆化解决 SG 函数的代码

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #include <numeric>
    #define debug() puts("++++")
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    #define sz size()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    //#define all 1,n,1
    #define FOR(i,x,n)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.in", "r", stdin)
    #define freopenw freopen("out.out", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e17;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 1000 + 10;
    const int maxm = 100 + 2;
    const LL mod = 100000000;
    const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
    const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    
    bool isLeapYear(int x){
      if(x % 400 == 0)  return true;
      if(x % 100 == 0)  return false;
      if(x % 4 == 0)  return true;
      return false;
    }
    
    int nextDay(int x){
      int d = x % 100;  x /= 100;
      int m = x % 100;  x /= 100;
      int y = x;
      if(isLeapYear(y) ? monn[m] == d : mon[m] == d){
        d = 1; ++m;
        if(m > 12)  m = 1, ++y;
        return (y * 100 + m) * 100 + d;
      }
      return (y * 100 + m) * 100 + d + 1;
    }
    
    int nextMonth(int x){
      int d = x % 100;  x /= 100;
      int m = x % 100;  x /= 100;
      int y = x;
      if(m == 12)  return (y * 100 + 101) * 100 + d;
      if(m == 1 && d == 29)  return isLeapYear(y) ? (y * 100 + 2) * 100 + d : 0;
      if(m == 1 && d > 29)  return 0;
      if(mon[m+1] < d)  return 0;
      return (y * 100 + m + 1) * 100 + d;
    }
    
    map<int, bool> mp;
    const int last_date = 20011104;
    
    bool dfs(int x){
      if(mp.count(x))  return mp[x];
      bool &ans = mp[x];
      if(x == last_date)  return ans = false;
      int next = nextDay(x);
      if(!dfs(next))  return ans = true;
      if((next = nextMonth(x)) && next <= last_date && !dfs(next))  return ans = true;
      return ans = false;
    }
    
    int main(){
      int T;  cin >> T;
      int y, d;
      while(T-- && scanf("%d %d %d", &y, &m, &d) == 3){
        n = (y * 100 + m) * 100 + d;
        if(dfs(n))  puts("YES");
        else  puts("NO");
      }
      return 0;
    }
    

      

    下面是正解的代码

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #include <numeric>
    #define debug() puts("++++")
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    #define sz size()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    //#define all 1,n,1
    #define FOR(i,x,n)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.in", "r", stdin)
    #define freopenw freopen("out.out", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e17;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 1000 + 10;
    const int maxm = 100 + 2;
    const LL mod = 100000000;
    const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
    const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    
    
    int main(){
      int T;  cin >> T;
      while(T--){
        int y, d;
        scanf("%d %d %d", &y, &m, &d);
        if((m+d) % 2 == 0 || m == 9 && d == 30 || m == 11 && d == 30)  puts("YES");
        else  puts("NO");
      }
      return 0;
    }
    

      

  • 相关阅读:
    SQL Server-基础-经典SQL语句
    《程序是给自己看的还是给别人看的》
    中文写程序,何陋之有?
    ASP.NET 使用Ajax
    验证码帮助类
    js函数的四种调用方式以及对应的this指向
    C#相等性比较(转)
    HashTable、HashSet和Dictionary的区别
    MD5加密方法
    VS2015 & ReSharper 快捷键设置
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/8431914.html
Copyright © 2011-2022 走看看