• UVaLive 5760 Alice and Bob (博弈 + 记忆化搜索)


    题意:有 n 堆石子,有两种操作,一种是从一堆中拿走一个,另一种是把两堆合并起来,Alice 先拿,谁不能拿了谁输,问谁胜。

    析:某些堆石子数量为 1 是特殊,石子数量大于 1 个的都合并起来,再拿,这是最优的,因为都想另一个输,并且第二种操作是可以翻转胜负的,所以都会先采取第二个操作,但是砘数量为 1 却不是,所以要分开考虑,dp[i][j] 表示,数量为 1 的堆的个数,总的操作数为 j,先手胜还是负。

    考虑边界,如果剩下的都是 1 的,那么 i % 3 != 0 先手胜,

    如果没有 1了,那么那是 j % 2 != 0 先手胜,

    如果 j 只剩下一个了,那么就可以合并到 1, 

    操作有三种,第一种,从石子为 1 个的堆中拿一个

    第二种,从石子不为 1  的堆中拿一个

    第三种,把两个堆石子为 1 的进行合并,并放到总操作数中。

    代码如下:

    #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 be begin()
    #define ed end()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    //#define all 1,n,1
    #define FOR(i,n,x)  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 = 1e5 + 10;
    const int maxm = 1e6 + 10;
    const LL mod = 1000000007;
    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;
    }
    inline int readInt(){ int x;  scanf("%d", &x);  return x; }
    
    int dp[55][1000 * 50+100];
    
    bool dfs(int n, int m){
      int &ans = dp[n][m];
      if(ans >= 0)  return ans;
      if(n == 0)  return ans = m&1;
      if(m == 0)  return ans = (n % 3 != 0);
      if(m == 1)  return ans = dfs(n+1, 0);
      if(!dfs(n-1, m))  return ans = 1;
      if(!dfs(n, m-1))  return ans = 1;
      if(!dfs(n-1, m+1))  return ans = 1;
      if(n > 1 & !dfs(n-2, m + 3))  return ans = 1;
      return ans = 0;
    }
    
    int main(){
      ms(dp, -1);
      int T;  cin >> T;
      for(int kase = 1; kase <= T; ++kase){
        scanf("%d", &n);
        int cnt1 = 0, sum = 0;
        for(int i = 1; i <= n; ++i){
          int x = readInt();
          if(x == 1)  ++cnt1;
          else  sum += x;
        }
        sum += max(0, n - cnt1 - 1);
        printf("Case #%d: %s
    ", kase, dfs(cnt1, sum) ? "Alice" : "Bob");
      }
      return 0;
    }
    

      

  • 相关阅读:
    预处理01 零基础入门学习C语言50
    内中断01 零基础入门学习汇编语言60
    预处理03 零基础入门学习C语言52
    预处理02 零基础入门学习C语言51
    对《移动互联网白皮书(2013年)》的几个解读
    Windows Azure Mobile Services增加了对 Android的支持并扩展其适用范围至东亚地区
    中国将自主研发操作系统对抗谷歌
    Windows Azure2.5天免费深度技术训练营——面向软件工程师和架构师
    Windows Azure Store:扩大服务市场
    use Visual studio2012 developing kernel driver monitor thread creation on Windows8
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/8964623.html
Copyright © 2020-2023  润新知