1. 程式人生 > >ZOJ-3964 Yet Another Game of Stones

ZOJ-3964 Yet Another Game of Stones

acm 直接 main flag ace online turn first 情況

Yet Another Game of Stones

題意: Alice 和 Bob 在進行取石子遊戲, 現在一共有n堆石子, 每堆石頭有ai個, 然後每堆石頭有一個bi屬性, 如果bi == 0, Alice取這堆石頭就沒有限制, 如果bi == 1 那麽Alice對這堆石子一次只能取奇數個, 如果bi == 2那麽Alice 對這堆石頭一次只能取奇數個, 所有石頭堆對於Bob來說說取法都沒有限制。

題解:首先我們可以知道 如果存在一個 a = 1, b = 2。 那麽Alice無法取這堆, Bob只要將這一堆留到最後, 當其他堆取完的時候下一個是Alice, Alice不能取這堆,所以Bob贏了, 如果下一個取的人是Bob, Bob可以取這一堆, 當Bob取完這一堆的時候,Alice沒有東西取所以Bob贏了。

如果存在一個 a = 偶數, b = 1, 那麽Alice最少要分2次奇數去取,如果就剩下這一堆的時候, 輪到Alice, Alice取完之後 Bob還能拿走剩下的,所以Bob贏了,如果輪到Bob, Bob可以直接取完, 所以Bob還是勝利的。

如果 a = 偶數, b = 2, Alice就可以直接將這一堆取完, 就不會讓Bob形成 a = 1, b = 2的情況, 但是 如果有另外一堆 a = 偶數, b = 2的石頭, Alice 可以取完2堆中的一堆, 但是Bob可以使得另外一堆形成 a = 1, b = 2的狀態, Bob就必勝了。也就是說如果有2堆 b = 2, Bob必勝, 如果 a = 奇數, b = 2, Bob必勝。

現在來看 b = 1的情況, 如果b = 1, Alice 不先手將這一堆取完或者 將這一堆變成剩余1的狀態, Bob就可以將這一堆變成a = 2, b = 1, 那麽Bob 就不會輸了。

所以如果有2堆 b = 1 && a != 1, Alice 可以解決一堆, 但是Bob就可以將另一堆變成 a = 2, b = 1的狀態, Bob也會勝利。

由上面來看, 當b =1 || b = 2的時候, Alice 都要先解決這一堆, 如果有另外一堆 b == 1||b==2,Bob就可以形成將這堆石頭變成不會失敗的狀態。

當然 如果 只有b = 0的情況, 那麽Nimi 博弈 的結論就適用了。

所以:當然 有一個 b = 1, a = 奇, 那麽ALice 要先手將這堆取完, 並且對於別的堆來說 先後手就改變了。

如果有一個 b = 1, a = 偶數, 那麽ALice要先手將這堆取成剩下數目為1, 那麽將這個1 也放進nimi就, 並且改變先後手的狀態就好了。

如果有一個 b = 2, a = 偶數, 那麽ALice 要先手將這堆取完, 並且對於別的堆來說 先後手就改變了。

如果有一個b = 2, a = 奇數, 那麽ALice就已經輸了。

如果出現2堆上述的特殊狀態, 那麽ALice也輸了。

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned LL
 5 #define fi first
 6 #define se second
 7 #define lson l,m,rt<<1
 8 #define rson m+1,r,rt<<1|1
 9 #define max3(a,b,c) max(a,max(b,c))
10 const int INF = 0x3f3f3f3f;
11 const LL mod = 1e9+7;
12 typedef pair<int,int> pll;
13 const int N = 1e5+5;
14 int a[N], b[N];
15 int main(){
16     int T;
17     scanf("%d",&T);
18     while(T--){
19         int n, t = 0, cnt = 0, flag = 0;
20         scanf("%d",&n);
21         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
22         for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
23         for(int i = 1; i <= n; i++){
24             if(b[i] == 0){
25                 t ^= a[i];
26             }
27             else if(b[i] == 1 && a[i] == 1) t ^= a[i];
28             else if(b[i] == 1 && a[i]&1) cnt++;
29             else if(b[i] == 1 && a[i]%2 == 0) cnt++, t ^= 1;
30             else if(b[i] == 2 && a[i]&1) flag = 1;
31             else if(b[i] == 2 && a[i]%2 == 0) cnt++;
32         }
33         if(flag || cnt >= 2) cout << "Bob\n";
34         else {
35             if(t != 0){
36                 if(cnt == 0) cout << "Alice\n";
37                 else cout << "Bob\n";
38             }
39             else {
40                 if(cnt != 0) cout << "Alice\n";
41                 else cout << "Bob\n";
42             }
43         }
44     }
45     return 0;
46 }

ZOJ-3964 Yet Another Game of Stones