제출 #597865

#제출 시각아이디문제언어결과실행 시간메모리
597865cjoa바이러스 (JOI19_virus)C++17
20 / 100
2085 ms133036 KiB
#include <iostream> #include <vector> #include <stack> #include <queue> #include <set> #include <algorithm> #include <cassert> using namespace std; #ifdef LOCAL_DEBUG #include <local_debug.h> #define DEBUG(...) DBG2::cprint(#__VA_ARGS__, __LINE__, __VA_ARGS__) #else #define DEBUG(...) #endif using VI = vector<int>; using VVI = vector<VI>; int M, R, C; string D; int U[801][801]; int max_runs[1<<4]; const string DIR = "NESW"; // direction wind blows from int dr[] = {-1, 0, +1, 0}; int dc[] = { 0, +1, 0, -1}; void dfs1(const VVI& G, VI& vis, stack<int>& S, int u) { vis[u] = true; for (int v : G[u]) { if (!vis[v]) dfs1(G, vis, S, v); } S.push(u); } void dfs2(const VVI& G, VI& vis, VI& comp, int u) { vis[u] = true; comp.push_back(u); for (int v : G[u]) { if (!vis[v]) dfs2(G, vis, comp, v); } } const int INF = 1e9 + 7; int infected_mask[801][801]; int bfs(const VI& sources, VI& vis, const VI& COMP_IDs, int comp_id, VI& ans) { queue<int> q; for (int src : sources) { if (U[src / C][src % C] == 0) return INF; q.push(src); vis[src] = comp_id; } bool ok = true; VI visited_nodes; while (!q.empty()) { int u = q.front(); q.pop(); visited_nodes.push_back(u); // assert(cnt < R*C*2); int r = u/C, c = u % C; for (int d = 0; d < 4; ++d) { int nr = r + dr[d], nc = c + dc[d]; if (nr < 0 or nr >= R or nc < 0 or nc >= C) continue; if (U[nr][nc] == 0) continue; int nmask = (infected_mask[nr][nc] |= 1<<((d+2)%4)); if ( max_runs[nmask] < U[nr][nc] ) continue; int v = nr * C + nc; if (COMP_IDs[v] > comp_id) { ok = false; break; } if (vis[v] != comp_id) { q.push(v); vis[v] = comp_id; } } } int res = INF; if (ok) { res = visited_nodes.size(); for (int u : visited_nodes) ans[u] = min(ans[u], res); } for (int u : visited_nodes) { int r = u / C, c = u % C; for (int d = 0; d < 4; d++) { int nr = r + dr[d], nc = c + dc[d]; if (nr < 0 or nr >= R or nc < 0 or nc >= C) continue; infected_mask[nr][nc] = 0; } } return res; } int main(int argc, char* argv[]) { ios_base::sync_with_stdio(false); cin.tie(nullptr); cin >> M >> R >> C; cin >> D; for (int r = 0; r < R; ++r) for (int c = 0; c < C; ++c) cin >> U[r][c]; D += D; auto matches = [](int mask, char c) -> bool { size_t d = DIR.find(c); assert(d != string::npos); return (mask & (1<<d)) != 0; }; for (int mask = (1<<4)-1; mask > 0; --mask) { for (int k = 0, run = 0; k <= int(D.size()); k++) { if (k == int(D.size()) or not matches(mask, D[k])) { max_runs[mask] = max(max_runs[mask], run); run = 0; } else ++run; } if (max_runs[mask] >= M) max_runs[mask] = INF; // DEBUG(mask, max_runs[mask]); } const int NUM_NODES = R*C; auto NODE_ID = [](int r, int c) -> int { return r*C + c; }; VVI G(NUM_NODES); for (int r = 0; r < R; ++r) { for (int c = 0; c < C; ++c) { if (U[r][c] == 0) continue; for (int d = 0; d < 4; ++d) { if (U[r][c] > max_runs[1<<d]) continue; int pr = r + dr[d], pc = c + dc[d]; if (pr < 0 or pr >= R or pc < 0 or pc >= C or U[pr][pc] == 0) continue; G[NODE_ID(pr, pc)].push_back(NODE_ID(r, c)); } } } VI vis(NUM_NODES, false); stack<int> S; for (int src = 0; src < NUM_NODES; ++src) if (!vis[src]) dfs1(G, vis, S, src); VVI Grev(NUM_NODES); for (int u = 0; u < NUM_NODES; ++u) for (int v : G[u]) Grev[v].push_back(u); vis = VI(NUM_NODES, false); VVI SCC; VI COMP_IDs(NUM_NODES, -1); while (!S.empty()) { int u = S.top(); S.pop(); if (!vis[u]) { VI comp; dfs2(Grev, vis, comp, u); int comp_id = SCC.size(); for (int u : comp) COMP_IDs[u] = comp_id; SCC.push_back(comp); } } /* auto is_root = [&](int comp_id) -> bool { for (int u : SCC[comp_id]) for (int v : G[u]) if (COMP_IDs[v] > COMP_IDs[u]) return false; return true; }; */ int best_count = INF; VI ans(NUM_NODES, INF); vis = VI(NUM_NODES, INF); for (int comp_id = int(SCC.size()) - 1; comp_id >= 0; comp_id--) { /* cerr << comp_id << ":"; for (int u : SCC[comp_id]) cerr << " (" << u/C << ',' << u%C << ")"; cerr << endl; */ int cnt = bfs( SCC[comp_id], vis, COMP_IDs, comp_id, ans ); // DEBUG(comp_id, cnt); best_count = min(best_count, cnt); } cout << best_count << '\n'; if (best_count < INF) cout << count(ans.begin(), ans.end(), best_count) << '\n'; else cout << 0 << '\n'; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...