stone(某博弈論題)
阿新 • • 發佈:2018-11-08
題目描述
有三堆石子,它們的石子個數分別為 x,y,z。
A 和 B 正在博弈,由 A 先手,雙方輪流操作。
每次操作是指,選擇若干堆(1~3 堆)石子,從中各取出相同數量的石子(不能 1 個都不取)。不能操作的人失
敗。
請判定是否先手必勝。
先考慮兩堆,先手必敗的情況
(1,2),(3,5),(4,7),(6,10),(8,13);
每對兩堆石子的差不相同,且每個數只出現了一次。
對於每個x,有唯一個y和它對應,出現先手必敗的情況
考慮三堆 (a,b,c)
我們可以類比出每對a,b對應這有且只有一個c和它組成先手必敗的情況。
對於(a,b,k)是先手必敗的情況,c 為大於k的某一個數。
那麼(a+c-k,b+c-k)組成先手必敗的情況的第三堆的石子數不可能為c.
因為如果(a+c-k,b+c-k,c)為成先手必敗的情況,那麼先手同時在第1堆和第二堆取走c-k時(a,b,c)則為先手必敗的情況,那麼(a,b,k)則不可能為先手必敗的情況,矛盾了所以(a+c-k,b+c-k)組成先手必敗的情況的第三堆的石子數不可能為c.
同理(a+c-k,b),(a,b+c-k)為成先手必敗的情況的第三堆的石子數也不可能為c。
那麼c與(a,b)構成先手必敗的情況的條件是,a和b沒有在第三堆為c時出現過,a-b沒有在第三堆為c時出現過。
#include<bits/stdc++.h> using namespace std; const int ha = 301; int f[ha+5][ha+5], bu[ha+5][ha+5],vis[1000],cha[1000]; void yuchuli() { for(int i = 0; i <= ha; i++) for(int j = 0; j <= ha; j++) f[i][j] = 1e9; memset(bu,0,sizeof(bu)); for(int cc = 0; cc <= ha; cc++) { int c = cc + 1; for(int a = 0; a <= ha; a++) for(int b = 0; b <= a; b++) { if(f[a][b] < cc) { int k = f[a][b]; int v = cc - k; if((a + v) <= ha) bu[a + v][b] = c; if((b + v) <= ha) bu[a][b+ v] = c; if(max(b+ v,a+ v) <= ha)bu[a+ v][b+v] = c; } else if(max(bu[a][b],bu[b][a]) < c && (vis[a] < c) && (vis[b] < c) && (cha[abs(a - b)] < c)) { if(cc == 301) int haha = 1; f[a][b] = f[b][a] = cc; vis[a] = c; vis[b] = c; cha[abs(a - b)] = c; } } } } int main() { yuchuli(); int t; cin >> t; for(int i = 1; i <= t; i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); if(f[x][y] == c) cout << "No" << endl; else cout << "Yes" << endl; } return 0; }
.