Submission #800815

#TimeUsernameProblemLanguageResultExecution timeMemory
800815rnl42Virus Experiment (JOI19_virus)C++14
100 / 100
354 ms24804 KiB
#include <bits/stdc++.h>
using namespace std;
#define amax(a, b) a = max(a, b)
#define cellid(r, c) (r*C+c)
#define extract(cell) (cell/C)][(cell%C)

constexpr int INF = 1e9+42;
    
int M, R, C;
vector<vector<int>> U;
    
string to_s(int cell) {
    return to_string(cell/C)+","+to_string(cell%C);
}
    
struct patate {
    int centre;
    int num_cases = 1;
    bool operator<(const patate& other) const {
        return num_cases > other.num_cases;
    }
};
    
struct Dir {
    int v, h;
    inline bool ok(int cell) {
        int r = cell/C, c = cell%C;
        if (0 <= r+v && r+v < R && 0 <= c+h && c+h < C && U[r+v][c+h]) {
            return true;
        } else {
            return false;
        }
    }
    inline int next(int cell) {
        return cell+h+v*C;
    }
};
    
const Dir DIRS[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    
int maxconsecutive[1<<4];
vector<int> uf;
vector<int> numchilds;
priority_queue<patate> pq;
int timer = 1;
vector<int> vu;
vector<int> bestcost;
vector<bool> potentiel_opt;
int ans = INF;
int ansq = 0;

int root(int u) {
    return uf[u] == u ? u : uf[u] = root(uf[u]);
}
    
int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> M >> R >> C;
    string dirs;
    cin >> dirs;
    dirs.append(dirs);
    char _map[256];
    _map['S'] = 0;
    _map['W'] = 1;
    _map['N'] = 2;
    _map['E'] = 3;
    uf.resize(R*C);
    vu.resize(R*C);
    numchilds.assign(R*C, 1);
    bestcost.assign(R*C, INF);
    potentiel_opt.resize(R*C);
    iota(uf.begin(), uf.end(), 0);
    for (int mask = 0; mask < 1<<4; mask++) {
        int l = 0;
        for (char c : dirs) {
            if ((mask >> _map[(unsigned char)c]) & 1) l++;
            else l = 0;
            maxconsecutive[mask] = max(maxconsecutive[mask], l);
        }
        if (maxconsecutive[mask] >= M) maxconsecutive[mask] = INF;
    }
    U.assign(R, vector<int>(C));
    for (int r = 0; r < R; r++) {
        for (int c = 0; c < C; c++) {
            cin >> U[r][c];
            if (U[r][c]) {
                pq.push({cellid(r, c), 1});
            }
        }
    }
    
    while (!pq.empty()) {
        auto cur = pq.top(); pq.pop();
        if (root(cur.centre) != cur.centre || numchilds[cur.centre] != cur.num_cases) continue;
    
        timer++;
        queue<int> q;
        q.push(cur.centre);
        vu[cur.centre] = timer;
        bool stopbfs = false;
        int num_explore = 0;
        vector<int> explored;
        while (!q.empty() && !stopbfs) {
            auto u = q.front(); q.pop();
            explored.push_back(u);
            num_explore++;
            for (auto dir : DIRS) {
                int next = dir.next(u);
                if (dir.ok(u)) {
                    int i = 2;
                    int mask = 0;
                    for (auto dir2 : DIRS) {
                        int k = dir2.next(next);
                        if (dir2.ok(next) && vu[k] == vu[cur.centre]) {
                            mask += 1<<i;
                        }
                        i++, i &= 3;
                    }
                    if (U[extract(next)] <= maxconsecutive[mask]) {
                        if (vu[next] != timer && root(next) == cur.centre) {
                            vu[next] = timer;
                            q.push(next);
                        } else if (root(next) != cur.centre) {
                            uf[cur.centre] = root(next);
                            numchilds[root(next)] += numchilds[cur.centre];
                            if (!potentiel_opt[root(next)]) pq.push({root(next), numchilds[root(next)]});
                            stopbfs = true;
                            break;
                        }
                    }
                }
            }
        }
        if (!stopbfs) {
            if (num_explore == ans) {
                ansq += num_explore;
            } else if (num_explore < ans) {
                ans = num_explore;
                ansq = num_explore;
            }
            potentiel_opt[cur.centre] = true;

        }
    }

    cout << ans << '\n' << ansq << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...