Study hard
(c++)백준 17142번: 연구소 3 본문
17142번: 연구소 3
인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고
www.acmicpc.net
[풀이]
dfs 조합으로 활성화시킬 바이러스 M개를 뽑고, 그에 따라 bfs를 이용하여 확산시켜야 하는 문제였다.
bfs level(깊이)갱신을 잘못 이해해서 애먹었다. 각 칸마다 점수가 있는게 아니므로 처음방문 했을 때 시간이 최단 시간임을 명심하자! 한 번 방문했으면 다시 방문하지 않아도 됨!!
빈칸을 미리 세어두고 바이러스를 확산시켰을 때 방문하는 빈칸들의 개수와 비교하여 같으면 최솟값을 갱신하였다.
각 경우마다 모든 빈 칸에 바이러스 퍼뜨리는 시간은 가장 마지막으로 방문되는 빈칸이 채워지는 시간이다.
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>//memset
#include <algorithm>//min
using namespace std;
struct Pos {
int x, y;
};
int N, M;
int Map[50][50];
int spread[50][50];//화산되는 시간 저장에 사용
vector<Pos>v;//바이러스 위치 저장
bool Select[10];//활성시킬 바이러스 체크
const int dx[] = { -1,1,0,0 };
const int dy[] = { 0,0,-1,1 };
int Min = 987654321;
int emptyPlace = 0;
int virusCnt = 0;
void bfs() {
memset(spread, -1, sizeof(spread));
queue<Pos>q;
//활성시킬 바이러스들 미리 큐에 넣어두기
for (int i = 0; i < virusCnt; i++) {
if (Select[i] == true) {
q.push({ v[i].x,v[i].y });
//0초부터 시작
spread[v[i].x][v[i].y] = 0;
}
}
int spreadPlace = 0;
int totalTime = 0;
while (!q.empty()) {
int x = q.front().x;
int y = q.front().y;
q.pop();
//상하좌우 확산
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= N || ny < 0 || ny >= N)
continue;
if (Map[nx][ny] == 1)
continue;
/*if (Map[nx][ny] != 1 && spread[nx][ny] == -1) {
spread[nx][ny] = spread[x][y] + 1;
if (Map[nx][ny] == 0) {
spreadPlace++;
totalTime = spread[nx][ny];
}
q.push({ nx,ny });
}*/
//다음 칸이 비활성 바이러스면
if (Map[nx][ny] == 2 && spread[nx][ny] == -1) {
//활성으로 바꾸고 큐에 넣어주기
spread[nx][ny] = spread[x][y] + 1;
q.push({ nx,ny });
}
//다음 칸이 빈칸이면
else if (Map[nx][ny] == 0 && spread[nx][ny] == -1) {
spread[nx][ny] = spread[x][y] + 1;
q.push({ nx,ny });
spreadPlace++;
//마지막엔 처음 활성 바이러스로부터 가장 멀리 떨어진 칸이 채워짐
totalTime = spread[nx][ny];
}
}
}
//모두 퍼뜨렸으면
if (spreadPlace == emptyPlace)
Min = min(Min, totalTime);
}
void getActiveVirus(int idx, int cnt) {
if (cnt == M) {
//확산시키기
bfs();
return;
}
for (int i = idx; i < virusCnt; i++) {
if (Select[i] == true)
continue;
Select[i] = true;
getActiveVirus(i, cnt + 1);
Select[i] = false;
}
}
void solution() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> Map[i][j];
if (Map[i][j] == 2) {
//비활성 바이러스 위치 저장
v.push_back({ i,j });
virusCnt++;
}
//빈칸 개수 미리 세어두기
if (Map[i][j] == 0)
emptyPlace++;
}
}
getActiveVirus(0, 0);
/*
cout << '\n';
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << spread[i][j] << ' ';
}
cout << '\n';
}
*/
if (Min == 987654321)
Min = -1;
cout << Min << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
solution();
return 0;
}
'백준 > bfs, dfs' 카테고리의 다른 글
(c++)백준 16946번: 벽 부수고 이동하기 4 (0) | 2021.02.07 |
---|---|
(c++)백준 16236번: 아기 상어 (0) | 2020.10.17 |
(c++)백준 14889번: 스타트와 링크 (0) | 2020.10.17 |
(c++)백준 15684번: 사다리 조작 (0) | 2020.10.16 |
(c++)백준 12100번: 2048 (Easy) (0) | 2020.10.16 |