UVA10561 Treblecross —— SG博弈
生活随笔
收集整理的這篇文章主要介紹了
UVA10561 Treblecross —— SG博弈
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:https://vjudge.net/problem/UVA-10561
題意:
兩個人玩游戲,輪流操作:每次往里面添加一個X,第一個得到XXX的獲勝。
題解:
詳情請看《訓練指南》P139,以及代碼注釋。
代碼如下:
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <vector>
6 #include <cmath>
7 #include <queue>
8 #include <stack>
9 #include <map>
10 #include <string>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 const int INF = 2e9;
15 const LL LNF = 9e18;
16 const int MOD = 1e9+7;
17 const int MAXN = 1e3+10;
18
19 int SG[MAXN], vis[MAXN];
20 bool hav[MAXN]; //是否有‘X'
21
22 void getSG() //SG[Len]:'.'連續長度為Len時,往其中放一個'X'的游戲的SG值。
23 {
24 SG[0] = 0; //長度為0時,沒有后繼狀態,故SG[0] = mex{} = 0;
25 //長度為1、2、3時的后繼狀態為0, 故SG[1/2/3] = mex{SG[0]} = 1,之所以單獨拿出來,是因為
26 //他們的求法與后面的不一樣。
27 SG[1] = SG[2] = SG[3] = 1;
28 for(int Len = 4; Len<MAXN; Len++)
29 {
30 memset(vis, 0, sizeof(vis));
31 for(int pos = 1; pos<=(Len+1)/2; pos++)
32 {
33 //當放了一個'X'進去之后,原先的游戲因為禁區的出現而可能被分為兩個子游戲。
34 int val = SG[Len-pos-2];
35 if(pos>3) val ^= SG[pos-3];
36 vis[val] = 1;
37 }
38 for(int j = 0;;j++) if(!vis[j]){
39 SG[Len] = j;
40 break;
41 }
42 }
43 }
44
45 int len, ans[MAXN];
46 bool oneHit(int pos) //判斷在pos位置能否放置一個X然后贏得游戲
47 {
48 if(hav[pos]) return 0;
49 if(pos<=len-2&&hav[pos+1]&&hav[pos+2]) return 1;
50 if(pos>=3&&hav[pos-1]&&hav[pos-2]) return 1;
51 if(pos!=1&&pos!=len&&hav[pos-1]&&hav[pos+1]) return 1;
52 return 0;
53 }
54
55 bool prohibit(int pos) //判斷pos是否在禁區之內
56 {
57 return hav[pos]||(pos>=2&&hav[pos-1])||(pos>=3&&hav[pos-2])||
58 (pos<=len-1&&hav[pos+1])||(pos<=len-2&&hav[pos+2]);
59 }
60
61 int getVAL() //得到整個游戲的SG異或和
62 {
63 int val = 0, L = 0;
64 for(int i = 1; i<=len; i++)
65 {
66 if(prohibit(i)) val ^= SG[L], L = 0;
67 else L++;
68 }
69 val ^= SG[L];
70 return val;
71 }
72
73 void solve()
74 {
75 ans[0] = 0;
76 for(int i = 1; i<=len; i++) if(oneHit(i)) { //首先判斷先手是否能“一擊斃命”
77 ans[++ans[0]] = i;
78 for(++i; i<=len; i++)
79 if(oneHit(i)) ans[++ans[0]] = i;
80 return;
81 }
82 if(getVAL()) //否則,則利用SG來判斷輸贏
83 {
84 for(int i = 1; i<=len; i++) if(!prohibit(i)){
85 hav[i] = true; //因為先手處于必勝狀態,當先手走了一步之后,就輪到后手處于必敗狀態。
86 if(!getVAL()) ans[++ans[0]] = i;
87 hav[i] = false;
88 }
89 }
90 }
91
92 char str[MAXN];
93 int main()
94 {
95 getSG();
96 int T;
97 scanf("%d", &T);
98 while(T--)
99 {
100 scanf("%s", str+1);
101 len = strlen(str+1);
102 memset(hav, 0, sizeof(hav));
103 for(int i = 1; i<=len; i++)
104 hav[i] = (str[i]=='X');
105
106 solve();
107 if(!ans[0])
108 printf("LOSING
");
109 else
110 {
111 printf("WINNING
");
112 for(int i = 1; i<ans[0]; i++)
113 printf("%d ", ans[i]);
114 printf("%d
", ans[ans[0]]);
115 }
116 }
117 }
View Code
總結
以上是生活随笔為你收集整理的UVA10561 Treblecross —— SG博弈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 针对access数据库的增删改查
- 下一篇: 三极管导通条件