ZOJ-3964 Yet Another Game of Stones
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