Problem: ioi03_d
Categories: search, bit
Difficulty: easy
Time limit: 1000 ms | Memory limit: 64 MB

The N ($1 \le N \le 50$) cows in Farmer John's herd look very much alike and are numbered $1 \ldots N$. When Farmer John puts a cow to bed in her stall, he must determine which cow he is putting to bed so he can put her in the correct stall.

Cows are distinguished using P ($1 \le P \le 8$) properties, numbered $1 \ldots P$, each of which has three possible values. For example, the color of a cow's ear tag might be yellow, green, or red. For simplicity, the values of every property are represented as the letters 'X', 'Y', and 'Z'. Any pair of Farmer John's cows will differ in at least one property.

Write a program that, given the properties of the cows in Farmer John's herd, helps Farmer John determine which cow he is putting to bed. Your program can ask Farmer John no more than 100 questions of the form: Is the cow's value for some property $T$ in some set $S$?

Try to ask as few questions as possible to determine the cow.

Interaction

The first line of the input file contains two space-separated integers, $N$ and $P$.

Each of the next $N$ lines describes a cow's properties using $P$ space-separated letters. The first letter on each line is the value of property 1, and so on. The second line in the input file describes cow 1, the third line describes cow 2, etc. The question/answer phase takes place via standard input and standard output.

Your program asks a question about the cow being put to bed by writing to standard output a line that is a 'Q' followed by a space, the property number, a space, and a spaceseparated set of one or more values. For example, "Q 1 Z Y" means "Does property 1 have value either 'Z' or 'Y' for the cow being put to bed?". The property must be an integer in the range $1 \ldots P$. All values must be 'X', 'Y', or 'Z' and no value should be listed more than once for a single question.

After asking each question your program asks, read a single line containing a single integer. The integer $1$ means the value of the specified property of the cow being put to bed is in the set of values given; the integer $0$ means it is not.

The program's last line of output should be a 'C' followed by a space and a single integer that specifies the cow that your program has determined Farmer John is putting to bed.

Scoring

Correctness: 30% of points

Programs will receive full score on correctness only if the cow specified is the only cow that is consistent with the answers given. A program that asks more than 100 questions for a test case will receive no points for that test case.

Question count: 70% of points

The remaining points will be determined by the number of questions required to correctly determine the cow. The test cases are designed to reward minimizing the worst-case question count. Partial credit will be given for near-optimal question counts.

Example

Input

```
4 2
X Z
X Y
Y X
Y Y

0

1
```

Output

```
Q 1 X Z

Q 2 Y

C 4
```

Interactor / grader files:
guess_interactor.cpp: // IOI03_D (guess) - Guess Which Cow Interactor
#include <bits/stdc++.h>
using namespace std;

int N, P;
int target;  // target cow (1-indexed)
vector<vector<char>> cows;
int queries = 0;
int MAX_QUERIES;

void finish(int code, const char* msg) {
    fprintf(stderr, "%s\n", msg);
    FILE* tout = fopen("tout.txt", "w");
    if (tout) {
        fprintf(tout, "queries=%d\n", queries);
        fprintf(tout, "query_limit=%d\n", MAX_QUERIES);
        fclose(tout);
    }
    exit(code);
}

int main(int argc, char* argv[]) {
    if (argc < 3) {
        finish(2, "Usage: interactor <input_file> <answer_file>");
    }

    // Read input
    FILE* fin = fopen(argv[1], "r");
    if (!fin) finish(2, "Cannot open input file");

    fscanf(fin, "%d %d", &N, &P);
    cows.resize(N, vector<char>(P));

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
            char c;
            fscanf(fin, " %c", &c);
            cows[i][j] = c;
        }
    }
    fclose(fin);

    // Read answer (target cow)
    FILE* fans = fopen(argv[2], "r");
    if (!fans) finish(2, "Cannot open answer file");
    fscanf(fans, "%d", &target);
    fclose(fans);

    // Query limit based on problem constraints
    MAX_QUERIES = 3 * N;

    // Send N and P to solver
    printf("%d %d\n", N, P);
    // Send cow properties
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
            printf("%c%c", cows[i][j], j == P-1 ? '\n' : ' ');
        }
    }
    fflush(stdout);

    char cmd[10];
    while (scanf("%s", cmd) == 1) {
        if (cmd[0] == 'Q') {
            int prop;
            scanf("%d", &prop);

            queries++;
            if (queries > MAX_QUERIES) {
                finish(1, "WA: Query limit exceeded");
            }

            if (prop < 1 || prop > P) {
                finish(1, "WA: Invalid property");
            }

            // Read values until newline
            set<char> values;
            char c;
            while ((c = getchar()) != '\n' && c != EOF) {
                if (c != ' ') values.insert(c);
            }

            // Check if target cow's property is in values
            char target_val = cows[target - 1][prop - 1];
            printf("%d\n", values.count(target_val) ? 1 : 0);
            fflush(stdout);

        } else if (cmd[0] == 'C') {
            int guess;
            scanf("%d", &guess);

            if (guess == target) {
                finish(0, "OK");
            } else {
                finish(1, "WA: Wrong cow");
            }
        } else {
            finish(2, "PE: Unknown command");
        }
    }

    finish(2, "PE: No guess provided");
    return 0;
}

non_adaptive.cpp: // IOI03_D (guess) - Guess Which Cow Interactor
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static int queries = 0;
static int query_limit = 0;

void log_metrics() {
    tout << "queries=" << queries << endl;
    tout << "query_limit=" << query_limit << endl;
}

void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

int read_target_from_ans(const string& in_path) {
    string ans_path = in_path;
    size_t pos = ans_path.rfind(".in");
    if (pos != string::npos) {
        ans_path.replace(pos, 3, ".out");
    }
    ifstream ans(ans_path);
    int target = 1;
    if (ans) ans >> target;
    return target;
}

int main(int argc, char* argv[]) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    int target = read_target_from_ans(argv[1]);

    int N = inf.readInt();
    int P = inf.readInt();

    vector<vector<char>> cows(N, vector<char>(P));
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
            cows[i][j] = inf.readChar();
            if (cows[i][j] == ' ' || cows[i][j] == '\n') {
                j--;
                continue;
            }
        }
    }

    query_limit = 3 * N;
    log_metrics();

    cout << N << " " << P << endl;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
            cout << cows[i][j] << (j == P-1 ? '\n' : ' ');
        }
    }
    cout.flush();

    string cmd;
    while (cin >> cmd) {
        if (cmd == "Q") {
            int prop;
            if (!(cin >> prop)) {
                finish(_wa, "EOF after Q");
            }

            queries++;
            if (queries > query_limit) {
                finish(_wa, "Query limit exceeded");
            }

            if (prop < 1 || prop > P) {
                finish(_wa, "Invalid property index");
            }

            string line;
            getline(cin, line);
            set<char> values;
            for (char c : line) {
                if (c != ' ') values.insert(c);
            }

            char target_val = cows[target - 1][prop - 1];
            cout << (values.count(target_val) ? 1 : 0) << endl;
            cout.flush();

        } else if (cmd == "C") {
            int guess;
            if (!(cin >> guess)) {
                finish(_wa, "EOF after C");
            }

            if (guess == target) {
                finish(_ok, "Correct");
            } else {
                finish(_wa, "Wrong cow");
            }
        } else {
            finish(_pe, "Unknown command");
        }
    }

    finish(_pe, "No guess provided");
    return 0;
}