🧡 Programming/💻 코딩 테스트
[백준/C++] 17142 연구소3 (BFS)
g_____
2023. 2. 18. 15:23
💡 문제 설명
비활성 바이러스의 위치가 2로 표시되는데 연구실 바이러스 M개를 활성시킨다는 것은 2로 표시된 위치 중에서 M 개를 선택해서 바이러스를 뿌리겠다는 것이다. 그리고 전체 빈 공간을 바이러스(비활성,활성 포함)로 모두 채우는데 얼마나 걸리는 지를 계산 하는 문제이다.
전형적인 bfs이지만 조합이 한 번 들어갔다는 점에 있어서 아주 살짝 까다로운 느낌을 내려고 한 문제이다.
💡 문제 풀이
먼저 바이러스 정보들을 struct info에 저장하고 이 struct를 벡터로 구성하여 virus정보를 저장한다.
조합을 통해서 바이러스의 활성 상태를 on/off 해 주면서 조합을 구한다.
조합은 중복되지 않는 숫자들을 고르는 것이기 때문에 for (int i = inx ; i < virus.size() ; i ++ )
for 문에서 i가 inx부터 시작되는 것이 중요하다. 이 부분을 놓치면 조합이 아니라 순열을 고르게 되는 것이다.
활성화된 바이러스의 개수가 M개를 충족하였으 때 bfs(solve)를 돌면서 전체 빈공간을 채우는데 걸리는 최소 시간을 구한다. 매번 solve를 실행 할 때마다 visit 초기화를 해 주고 활성화된 바이러스들을 큐에 넣어주고 시작해야 한다.
#define _CRT_SECURE_NO_WARNINGS
#define ABS(A,B) A>B? A-B: B-A
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
int dx[4] = { 0,0,1,-1};
int dy[4] = {-1,1,0,0};
int map[55][55];
bool visit[55][55];
int N, M;
struct info { int y, x,time; bool active; };
std::vector<info> virus;
int time = 9876543210;
bool check = false;
int place;
void solve() {
std::queue<info> V;
memset(visit, 0, sizeof(visit));
for (int i = 0; i < virus.size(); i++) {
if (virus[i].active) {
V.push(virus[i]);
visit[virus[i].y][virus[i].x] = true;
}
}
int curVirus = 0;
while (!V.empty()) {
info head = V.front();
V.pop();
if (head.time > time) break;
for (int i = 0; i < 4; i++) {
int ny = head.y + dy[i];
int nx = head.x + dx[i];
if (ny < 0 || nx < 0 || ny >= N || nx >= N) continue;
if (visit[ny][nx] || map[ny][nx] == 1) continue;
if (map[ny][nx] == 0) {
visit[ny][nx] = true;
V.push({ ny,nx,head.time + 1,true });
curVirus++;
}
else if (map[ny][nx] == 2) {
visit[ny][nx] = true;
V.push({ ny,nx,head.time + 1,true });
}
}
if (curVirus == place) {
time = head.time+1 < time ? head.time+1 : time;
check = true;
break;
}
}
}
void comb(int inx, int cnt) {
if (cnt == M) {
solve();
return;
}
for (int i = inx; i < virus.size(); i++) {
if (virus[i].active) continue;
virus[i].active = true;
comb(i + 1, cnt + 1);
virus[i].active = false;
}
}
int main() {
scanf("%d %d", &N, &M);
for (int y = 0; y < N; y++) {
for (int x = 0; x < N; x++) {
scanf("%d", &map[y][x]);
if (map[y][x] == 2) virus.push_back({ y,x,0,false });
if (map[y][x] == 0) place++;
}
}
if (place == 0) {
printf("0");
return 0;
}
comb(0, 0);
if (!check) printf("-1");
else printf("%d", time);
return 0;
}