Cod sursa(job #253395)

Utilizator silviugSilviu-Ionut Ganceanu silviug Data 5 februarie 2009 18:58:26
Problema Episoade Scor Ascuns
Compilator cpp Status done
Runda Marime 4.99 kb
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

const int MAX_LEN = 1000;
const int MAX_TESTS = 20;
const int MAX_N = 100;

char expr[MAX_LEN];
int P[MAX_N];
int viz[MAX_N];
int len;

void split(int e_left, int e_right, int pos[], int len, int sets[][MAX_N]) {
    int p = 0, tmp = -1;
    for (int i = 0; i < MAX_N; ++i) {
        sets[i][0] = 0;
    }
    for (int i = e_left; i < e_right; ++i) {
        if ('0' <= expr[i] && expr[i] <= '9') {
            if (tmp == -1) {
                tmp = expr[i] - '0';
            } else {
                tmp = tmp * 10 + expr[i] - '0';
            }
        } else {
            if (tmp != -1) {
                sets[p][++sets[p][0]] = tmp;
                tmp = -1;
            }
        }
        if (i == pos[p]) {
            ++p;
        }
    }
    if (tmp != -1) {
        sets[p][++sets[p][0]] = tmp;
    }
}

int sets[MAX_N][MAX_N][MAX_N];

int eval(int lev, int e_left, int e_right, int p_left, int p_right) {
    fprintf(stderr, "%d (%d %d) (%d %d)\n", lev, e_left, e_right, p_left, p_right);
    if (p_left + 1 == p_right) {
        int dummy[1] = {-1};
        split(e_left, e_right, dummy, 0, sets[lev]);
        return sets[lev][0][0] == 1 && sets[lev][0][1] == P[p_left];
    }
    int depth = 0;
    int parallel_pos[MAX_N], serial_pos[MAX_N];
    int par_len = 0, ser_len = 0;
    for (int i = e_left; i < e_right; ++i) {
        if (expr[i] == '(') {
            ++depth;
        } else if (expr[i] == ')') {
            --depth;
        } else if (depth == 0) {
            if (expr[i] == '#') {
                parallel_pos[par_len++] = i;
            } else if (expr[i] == '>') {
                serial_pos[ser_len++] = i;
            }
        }
    }
    assert(depth == 0);

    if (par_len == 0 && ser_len == 0) {
        // No operator, eliminate a pair of paranthesis.
        return eval(lev, e_left + 1, e_right - 1, p_left, p_right);
    }
    int tmp_left, tmp_right;
    if (par_len > 0) {
        int used[MAX_N];
        memset(used, 0, sizeof(used));
        split(e_left, e_right, parallel_pos, par_len, sets[lev]);
        for (int i = 0; i <= par_len; ++i) {
            for (int j = 1; j <= sets[lev][i][0]; ++j) {
                fprintf(stderr, "%d ", sets[lev][i][j]);
            }
            fprintf(stderr, "\n");
        }
        fprintf(stderr, "----\n");
        for (int i = p_left; i < p_right;) {
            int setid = -1;
            for (int j = 0; j <= par_len && setid == -1; ++j) {
                if (used[j] == 0) {
                    for (int k = 1; k <= sets[lev][j][0]; ++k) {
                        if (sets[lev][j][k] == P[i]) {
                            used[j] = 1;
                            setid = j;
                            break;
                        }
                    }
                }
            }
            fprintf(stderr, "setid = %d\n", setid);
            if (setid == -1) {
                return 0;
            }
            if (setid == 0) {
                tmp_left = e_left;
                tmp_right = parallel_pos[setid];
            } else if (setid == par_len) {
                tmp_left = parallel_pos[setid - 1] + 1;
                tmp_right = e_right;
            } else {
                tmp_left = parallel_pos[setid - 1] + 1;
                tmp_right = parallel_pos[setid];
            }
            if (eval(lev + 1, tmp_left, tmp_right, i, i + sets[lev][setid][0]) == 0) {
                return 0;
            }
            i += sets[lev][setid][0];
        }
        return 1;
    } else {
        split(e_left, e_right, serial_pos, ser_len, sets[lev]);
        int setid = 0, i;
        for (i = p_left; i < p_right && setid <= ser_len;) {
            if (setid == 0) {
                tmp_left = e_left;
                tmp_right = serial_pos[setid];
            } else if (setid == ser_len) {
                tmp_left = serial_pos[setid - 1] + 1;
                tmp_right = e_right;
            } else {
                tmp_left = serial_pos[setid - 1] + 1;
                tmp_right = serial_pos[setid];
            }
            if (eval(lev + 1, tmp_left, tmp_right, i, i + sets[lev][setid][0]) == 0) {
                return 0;
            }
            i += sets[lev][setid][0];
            ++setid;
        }
        return i == p_right && setid > ser_len;
    }

    assert(0);
    return 0;
}

int main() {
    int N, T;
    freopen("episoade.in", "rt", stdin);
    freopen("episoade.out", "wt", stdout);
    char ch;
    while ((ch = fgetc(stdin)) != '\n') {
        assert(len < MAX_LEN);
        expr[len++] = ch;
    }
    scanf("%d %d\n", &T, &N);
    assert(0 < T && T <= MAX_TESTS);
    assert(0 < N && N <= MAX_N);
    for (int t = 0; t < T; ++t) {
        memset(viz, 0, sizeof(viz));
        for (int i = 0; i < N; ++i) {
            scanf("%d", P + i);
            assert(1 <= P[i] && P[i] <= N);
            assert(viz[P[i] - 1] == 0);
            viz[P[i] - 1] = 1;
        }
        printf("%d\n", eval(0, 0, len, 0, N));
        fprintf(stderr, "\n\n\n\n");
    }
    return 0;
}