Codetree. 바이러스 백신 문제 출처 1. 문제설명 NxN크기의 도시가 주어진다. 도시에는 바이러스, 벽, 병원이 있고, 각각 0, 1, 2로 표현된다. M개의 병원을 골라 최대한 빨리 바이러스를 없애려고 한다. 골라진 병원들을 시작으로 매 초마다 상하좌우로 인접한 지역 중 벽을 제외한 지역에 백신이 공급되어 바이러스가 사라진다. M개의 병원을 놓을 수 있는 조합 중 바이러스를 없애는데 걸리는 최소 시간을 구하라! 문제 분류 BFS, Backtracking 2. 알고리즘 설계 M개의 조합을 dfs로 구현 각 병원의 좌표를 벡터에 담아 bfs의 입력으로 사용 M개의 병원이 전부 선택되면 bfs 실행 {x, y, d} 구조체를 선언하고 큐에 삽입 d는 거리 한번 방문한 지점은 다시 방문하지 않아도 됨. 즉, 여러 개의 길이 존재해도 가장 가까이 있는 병원에 의해 최초 1회 갱신 3. 전체 코드 #define _CRT_SECURE_NO_WARNINGS #include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; const int INF = 5000; const int dx[] = { -1,1,0,0 }; const int dy[] = { 0,0,-1,1 }; int n, m, A[50][50], ans = INF; bool vis[50][50]; vector<pii> hospital; struct info { int x, y, d; }; int bfs(vector<pii> v) { queue<info> q; int mx = 0; for (int i = 0; i < n; i++) memset(vis[i], false, sizeof(vis[i])); for (auto& nxt : v) { q.push({ nxt.first, nxt.second, 0 }); vis[nxt.first][nxt.second] = true; } while (!q.empty()) { int q_sz = q.size(); while (q_sz--) { info cur = q.front(); q.pop(); if(A[cur.x][cur.y] == 0) mx = max(mx, cur.d); for (int dir = 0; dir < 4; dir++) { int nx = cur.x + dx[dir]; int ny = cur.y + dy[dir]; if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue; if (A[nx][ny] != 1 && !vis[nx][ny]) { q.push({ nx, ny, cur.d + 1 }); vis[nx][ny] = true; } } } } for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (A[i][j] == 0 && !vis[i][j]) return INF; return mx; } void solve(int s, int cnt, vector<pii> v) { if (cnt == m) { ans = min(ans, bfs(v)); return; } for (int i = s; i < hospital.size(); i++) { v.push_back(hospital[i]); solve(i + 1, cnt + 1, v); v.pop_back(); } } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); // freopen("input.txt", "r", stdin); cin >> n >> m; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> A[i][j]; if (A[i][j] == 2) hospital.push_back({ i,j }); } } solve(0, 0, {}); if (ans == INF) cout << -1; else cout << ans; return 0; } 4. 소감 단순한 BFS 문제였다. Posted on Jan 30, 2024