1. 程式人生 > >Alice and Bob HDU - 4111 (SG函數)

Alice and Bob HDU - 4111 (SG函數)

想要 scan pla using mem 進行 span pri gif

Alice and Bob are very smart guys and they like to play all kinds of games in their spare time. The most amazing thing is that they always find the best strategy, and that‘s why they feel bored again and again. They just invented a new game, as they usually did.
The rule of the new game is quite simple. At the beginning of the game, they write down N random positive integers, then they take turns (Alice first) to either:
1. Decrease a number by one.
2. Erase any two numbers and write down their sum.
Whenever a number is decreased to 0, it will be erased automatically. The game ends when all numbers are finally erased, and the one who cannot play in his(her) turn loses the game.
Here‘s the problem: Who will win the game if both use the best strategy? Find it out quickly, before they get bored of the game again!

InputThe first line contains an integer T(1 <= T <= 4000), indicating the number of test cases.

Each test case contains several lines.
The first line contains an integer N(1 <= N <= 50).
The next line contains N positive integers A 1 ....A N(1 <= A i <= 1000), represents the numbers they write down at the beginning of the game.OutputFor each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y is either "Alice" or "Bob".

Sample Input

3
3
1 1 2
2
3 4
3
2 3 5

Sample Output

Case #1: Alice
Case #2: Bob
Case #3: Bob

給出 n 個數,每次有兩種操作
1、任意取一個數字,讓他減一
2、把兩個數字合並起來
最後不能操作的人失敗

考慮全部不合並和全部合並的情況,操作次數的範圍是[∑a, ∑a + n - 1]。
如果每一堆石子全部大於1, ∑a + n - 1 就是先手能否贏。 因為如果這是一個奇數,後手想贏必須讓其中一堆沒有參與到合並,那麽後手一定要讓這一堆進行操作1,由於全部大於1,那麽不可能一步完成,先手只要每次把這堆合並起來就一定能贏。
反之同理,偶數時後手用同樣的方法限制先手,後手一定能贏。
那麽考慮有 1 的時候,如果這時候一方想要減少合並次數,只需要把 1 進行操作1,另一方無法阻止。則把 1 單獨拿出來。
用 sg[i][j] 表示有 i 個 1 ,除了 1 以外剩余堆可以進行的最多的操作次數。然後開始操作
(1)、在 i 裏面進行操作1
(2)、在 j 裏面進行操作1
(3)、讓 i 和 j 進行操作2
(4)、讓 i 和 i 進行操作2
然後進行轉移就可以了
然後其中的細節差不多有如下
1、當 i == 0時,j 的奇偶進就決定了能否贏
2、在(2)中,如果 j==2,會轉化一個到 i,自己變成0,變成sg[i+1][0]; 如果j>2,正常轉化,sg[i+1][j-1];
3、在(4)中,如果 j==0,轉化出來為sg[i-2][2]; 如果 j>0,那麽合並出來的新堆可以之前的 j 在合並一次,所以是sg[i-2][j+3]
技術分享圖片
/*
          .
         ‘;;;;;.
        ‘!;;;;;;!;`
       ‘!;|&#@|;;;;!:
      `;;!&####@|;;;;!:
     .;;;!&@$$%|!;;;;;;!‘.`:::::‘.
     ‘!;;;;;;;;!$@###&|;;|%!;!$|;;;;|&&;.
     :!;;;;!$@&%|;;;;;;;;;|!::!!:::;!$%;!$%`    ‘!%&#########@$!:.
     ;!;;!!;;;;;|$$&@##$;;;::‘‘‘‘‘::;;;;|&|%@$|;;;;;;;;;;;;;;;;!$;
     ;|;;;;;;;;;;;;;;;;;;!%@#####&!:::;!;;;;;;;;;;!&####@%!;;;;$%`
    `!!;;;;;;;;;;!|%%|!!;::;;|@##%|$|;;;;;;;;;;;;!|%$#####%;;;%&;
    :@###&!:;;!!||%%%%%|!;;;;;||;;;;||!$&&@@%;;;;;;;|$$##$;;;%@|
    ;|::;;;;;;;;;;;;|&&$|;;!$@&$!;;;;!;;;;;;;;;;;;;;;;!%|;;;%@%.
   `!!;;;;;;;!!!!;;;;;$@@@&&&&&@$!;!%|;;;;!||!;;;;;!|%%%!;;%@|.
%&&$!;;;;;!;;;;;;;;;;;|$&&&&&&&&&@@%!%%;!||!;;;;;;;;;;;;;$##!
!%;;;;;;!%!:;;;;;;;;;;!$&&&&&&&&&&@##&%|||;;;!!||!;;;;;;;$&:
‘:|@###%;:;;;;;;;;;;;;!%$&&&&&&@@$!;;;;;;;!!!;;;;;%&!;;|&%.
 !@|;;;;;;;;;;;;;;;;;;|%|$&&$%&&|;;;;;;;;;;;;!;;;;;!&@@&‘
  .:%#&!;;;;;;;;;;;;;;!%|$$%%&@%;;;;;;;;;;;;;;;;;;;!&@:
  .%$;;;;;;;;;;;;;;;;;;|$$$$@&|;;;;;;;;;;;;;;;;;;;;%@%.
    !&!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|@#;
     `%$!;;;;;;;;;;;$@|;;;;;;;;;;;;;;;;;;;;;;;;!%$@#@|.
       .|@%!;;;;;;;;;!$&%||;;;;;;;;;;;;;;;;;!%$$$$$@#|.
           ;&$!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%#####|.
           |##$|!;;;;;;::‘‘:;;;;;;;;;;;;;!%$$$@#@;
          ;@&|;;;;;;;::‘‘‘‘‘‘:;;;;;;;|$&@###@|`
        .%##@|;;;;:::‘‘‘‘‘‘‘‘‘‘::;!%&##$‘
      `$##@$$@@&|!!;;;:‘‘‘‘‘::::;;;;;|&#%.
    ;&@##&$%!;;;;;;::‘‘‘‘‘‘‘‘::;!|%$@#@&@@:
     .%@&$$|;;;;;;;;;;:‘‘‘‘:‘‘‘‘::;;;%@#@@#%.
    :@##@###@$$$$$|;;:‘‘‘‘:;;!!;;;;;;!$#@@#$;`
     `%@$$|;;;;;;;;:‘‘‘‘‘‘‘::;;;;|%$$|!!&###&‘
     |##&%!;;;;;::‘‘‘‘‘‘‘‘‘‘‘‘::;;;;;;;!$@&:`!‘
    :;!@$|;;;;;;;::‘‘‘‘‘‘‘‘‘‘‘:;;;;;;;;!%&@$:                 !@#$‘
      |##@@&%;;;;;::‘‘‘‘‘‘‘‘‘:;;;;;;;!%&@#@$%:              ‘%%!%&;
      |&%!;;;;;;;%$!:‘‘‘‘‘‘‘:|%!;;;;;;;;|&@%||`            ‘%$|!%&;
      |@%!;;!!;;;||;:‘‘‘‘‘‘:;%$!;;;;!%%%&#&%$&:           .|%;:!&%`
      !@&%;;;;;;;||;;;:‘‘::;;%$!;;;;;;;|&@%;!$;          `%&%!!$&:
      ‘$$|;!!!!;;||;;;;;;;;;;%%;;;;;;;|@@|!$##;         !$!;:!$&:
       |#&|;;;;;;!||;;;;;;;;!%|;;;;!$##$;;;;|%‘      `%$|%%;|&$‘
        |&%!;;;;;;|%;;;;;;;;$$;;;;;;|&&|!|%&&;  .:%&$!;;;:!$@!
        `%#&%!!;;;;||;;;;;!$&|;;;!%%%@&!;;;!!;;;|%!;;%@$!%@!
        !&!;;;;;;;;;||;;%&!;;;;;;;;;%@&!;;!&$;;;|&%;;;%@%`
       ‘%|;;;;;;;;!!|$|%&%;;;;;;;;;;|&#&|!!||!!|%$@@|‘
       .!%%&%‘`|$;       :|$#%|@#&;%#%.
*/
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e4 + 50;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int sg[55][maxn];

void dfs(int x, int y) {
    if(sg[x][y] != -1)    return ;
    if(x == 0) {
        sg[x][y] = y&1;
        return ;
    }
    if(x) {
        dfs(x-1, y);
        if(sg[x-1][y] == 0) {
            sg[x][y] = 1;
            return ;
        }
    }
    if(y) {
        dfs(x-1, y+1);
        if(sg[x-1][y+1] == 0) {
            sg[x][y] = 1;
            return ;
        }
    }
    if(x > 1) {
        if(y) {
            dfs(x-2, y+3);
            if(sg[x-2][y+3] == 0) {
                sg[x][y] = 1;
                return ;
            }
        } else {
            dfs(x-2, 2);
            if(sg[x-2][2] == 0) {
                sg[x][y] = 1;
                return ;
            }
        }
    }
    if(y > 1) {
        if(y > 2) {
            dfs(x, y-1);
            if(sg[x][y-1] == 0) {
                sg[x][y] = 1;
                return ;
            }
        } else {
            dfs(x+1, 0);
            if(sg[x+1][0] == 0) {
                sg[x][y] = 1;
                return ;
            }
        }
    }
    sg[x][y] = 0;
    return ;
}

int main() {
    mes(sg, -1);
    sg[0][0] = 0;
    cas = 1;
    scanf("%d", &T);
    while(T--) {
        int ans = 0, cnt = 0;
        scanf("%d", &n);
        for(int i=1, x; i<=n; i++) {
            scanf("%d", &x);
            if(x > 1)
                ans += x+1;
            else
                cnt++;
        }
        if(ans)
            ans--;
        if(sg[cnt][ans] == -1)
            dfs(cnt, ans);
        printf("Case #%d: %s\n", cas++, sg[cnt][ans] ? "Alice" : "Bob");
    }
    return 0;
}
View Code

Alice and Bob HDU - 4111 (SG函數)