A Lot of Games(Trie树 + 博弈)

题目链接:http://codeforces.com/contest/455/problem/B

题意:n, k 分别表示 字符串组数 和 比赛次数。  从一个空单词开始, a,b二人分别轮流往单词后添加一个字母,要求每次添加后的结果给字符串中至少其中一个的前缀, 无法继续添加者,该场比赛输, 下场比赛由前场输者为先手。第 k 次比赛的输赢表示总比赛的输赢。 

题解:每场比赛先手共4情况:1。必赢   2。必输  3。想赢便赢, 想输便输 4 胜负无法自己把握  四种情况分别二进制表示 01, 10, 11, 00   

当情况4时,只要后手  在前(k - 1)场输, 第k 场赢, 则后手必赢

当情况3时, 只要先手 在前(k - 1)场输,第k场赢, 则先手必赢

当情况2 时, 只要后手 每场均赢, 则时 先手一直为先手 , 则后手赢 

当情况1时, 当 k 为奇数  先手赢, 可为偶数 后手赢 (从最后比赛往前推一下便可知道)

由此,可用字典树 , 子树的 最后一个节点标记res(01),  父节点 |= ~子节点, 可用 深搜完成

 1 /***Good Luck***/
 2 #define _CRT_SECURE_NO_WARNINGS
 3 #include <iostream>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <cstring>
 7 #include <string>
 8 #include <algorithm>
 9 #include <stack>
10 #include <map>
11 #include <queue>
12 #include <vector>
13 #include <set>
14 #include <functional>
15 #include <cmath>
16 
17 #define Zero(a) memset(a, 0, sizeof(a))
18 #define Neg(a)  memset(a, -1, sizeof(a))
19 #define All(a) a.begin(), a.end()
20 #define PB push_back
21 #define inf 0x3f3f3f3f
22 #define inf2 0x7fffffffffffffff
23 #define ll long long
24 using namespace std;
25 //#pragma comment(linker, "/STACK:102400000,102400000") 
26 
27 typedef struct tree {
28     struct tree *br[26];
29     int res;
30 }Node;
31 
32 Node* head = new Node;
33 
34 void Tree_Insert(char str[]) {  //建树
35     Node *t, *s = head;
36     int i, j;
37     int len = strlen(str) - 1;
38     for (i = 0; i <= len; ++i) {
39         int id = str[i] - 'a';
40         if (s->br[id] == NULL) {
41             t = new Node;
42             for (j = 0; j <= 25; ++j) {
43                 t->br[j] = NULL;
44             }
45             s->br[id] = t;
46         }
47         s = s->br[id];
48     }
49     s->res = 1;
50 }
51 
52 void dfs(Node* u) {  
53     int temp = 0;
54     bool flag = false;
55     for (int i = 0; i <= 25; ++i) {
56         Node* tmp = u->br[i];
57         if (tmp) {
58             dfs(tmp);        
59             temp |= ~(tmp->res); //  父节点 |= ~子节点
60             flag = true;
61         }
62     }
63     if (flag)
64     u->res = temp;
65 }
66 
67 int main() {
68     //freopen("data.out", "w", stdout);
69     //freopen("data.in", "r", stdin);
70     //cin.sync_with_stdio(false);
71     int n, k;
72     char s[100005];
73     cin >> n >> k;
74     for (int i = 0; i <= 25; ++i) {
75         head->br[i] = NULL;
76     }
77     for (int i = 0; i < n; ++i) {
78         scanf("%s", s);
79         Tree_Insert(s);
80     }
81     dfs(head);
82     int ans = head->res & 3;
83     if (ans == 3) {
84         cout << "First" << endl;
85         return 0;
86     } else if (ans == 1) {
87         cout << "Second" << endl;
88         return 0;
89     } else if (ans == 0) {
90         cout << "Second" << endl;
91         return 0;
92     } else {
93         if (k % 2) cout << "First" << endl;
94         else cout << "Second" << endl;
95     }
96 
97     return 0;
98 }

 

转载于:https://www.cnblogs.com/yeahpeng/p/3902890.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值