Skip to content

Commit 316d083

Browse files
committed
APIO 11 Guess :D
1 parent 26603e3 commit 316d083

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

APIO/APIO 11-guess.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
APIO 2011 Guess My Word
3+
- A state in this game consists of the following info:
4+
- The set of candidate words (cand)
5+
- The set of positions whose letters are already known (mask)
6+
- The number of remaining wrong guesses (rem)
7+
- If |cand| == 0 (i.e. A contradicted themselves), then B wins
8+
- Otherwise, if rem == 0 (i.e. B made too many wrong guesses),
9+
then A wins
10+
- Otherwise, if |cand| == 1 (i.e. B narrowed the set of words
11+
down to a single one), then B wins
12+
- Otherwise, the following happens:
13+
- B must guess a letter present in one of the candidates
14+
in a position whose letter is still unknown
15+
- A then chooses whether to confirm the letter and in which
16+
position, or to tell B that their guess was wrong
17+
- If A is able to force a win by using *any* such move
18+
*for all* possible letters that B guesses, then A wins;
19+
otherwise, B wins
20+
- No idea what the complexity is, but it's fast enough
21+
*/
22+
23+
#include <bits/stdc++.h>
24+
typedef long long ll;
25+
using namespace std;
26+
27+
string s[1000];
28+
vector<int> has_len[8];
29+
30+
bool possible(int len, vector<int> cand, int mask, int rem) {
31+
if (!cand.size()) return false;
32+
if (!rem) return true;
33+
if (cand.size() == 1) return false;
34+
35+
bool good[26];
36+
memset(good, 0, sizeof good);
37+
for (int i = 0; i < len; i++) if (!(mask & (1 << i))) {
38+
for (int j : cand) good[s[j][i] - 'A'] = true;
39+
}
40+
41+
bool all = true;
42+
for (char i = 'A'; i <= 'Z'; i++) if (good[i - 'A']) {
43+
vector<vector<int>> match(len);
44+
vector<int> nomatch;
45+
for (int j : cand) {
46+
bool found = false;
47+
for (int k = 0; k < len && !found; k++) if (s[j][k] == i) {
48+
match[k].push_back(j);
49+
found = true;
50+
}
51+
if (!found) nomatch.push_back(j);
52+
}
53+
bool any = possible(len, nomatch, mask, rem - 1);
54+
for (int j = 0; j < len && !any; j++) if (!(mask & (1 << j)))
55+
any = possible(len, match[j], mask + (1 << j), rem);
56+
all &= any;
57+
}
58+
return all;
59+
}
60+
61+
int main() {
62+
cin.tie(0)->sync_with_stdio(0);
63+
int t;
64+
cin >> t;
65+
while (t--) {
66+
int n;
67+
cin >> n;
68+
for (int i = 0; i < n; i++) {
69+
cin >> s[i];
70+
has_len[s[i].size()].push_back(i);
71+
}
72+
bool any = false;
73+
for (int i = 1; i <= 7; i++) {
74+
if (!any) any = possible(i, has_len[i], 0, i + 1);
75+
has_len[i].clear();
76+
}
77+
cout << (any ? "Yes" : "No") << '\n';
78+
}
79+
return 0;
80+
}

0 commit comments

Comments
 (0)