본문 바로가기
알고리즘

BOJ 17142 - 연구소3(C++)

by 장중앙 2021. 8. 25.

https://www.acmicpc.net/problem/17142

 

17142번: 연구소 3

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

www.acmicpc.net

풀이

0. 입력데이터에서 바이러스의 위치, 2번의 완료조건(바이러스가 퍼져야하는 방의 수)를 저장

1. 입력 데이터의 바이러스 중 M개의 바이러스를 활성화  

    - 모든 바이러스중 M개를 선택하여 모든 경우의 수에 대해 시뮬레이션(브루트포스)

2. 활성 상태의 바이러스는 상하좌우로 전파되며 모든 빈칸에 바이러스가 퍼지는 최소 시간을 구함

   - 1에 대한 모든 경우의 수에 bfs를 이용하여 바이러스가 퍼지는 시간을 구함

   - 퍼진 바이러스의 수 == 바이러스가 퍼져야하는 방의수(벽을 제외한 수)의 경우 최소시간을 비교/갱신

3. 모든 칸에 바이러스를 퍼뜨릴수 없는 경우는 -1을 출력

 

#include <cstring>
#include <vector>
#include <iostream>
#include <queue>

#define MAX 987654321
using namespace std;

int N, M;
int dy[] = { 0,1,0,-1 };
int dx[] = { 1,0,-1,0 };
int map[51][51];
bool visit[51][51];
vector<pair<int, int>> virus_pos;//모든 바이러스의 위치
vector<int> virus;//바이러스 전파시작전 활성화된 바이러스의 인덱스
int MIN = MAX;
int empty_cnt;

struct point {
    int y, x, dis;
};

void spread_virus() {
    memset(visit, false, sizeof(visit));
    queue<point> q;
    int y, x, dis,time=0;
    int virus_cnt = virus_pos.size();//현재 바이러스의 수, 비활성 바이러스도 포함

    for (int i = 0; i < virus.size(); i++) {//활성화한 바이러스를 큐와 visit에 갱신
        y = virus_pos[virus[i]].first;
        x= virus_pos[virus[i]].second;
        visit[y][x] = true;
        q.push(point{ y,x,0 });
    }

    while (!q.empty()) {
        y = q.front().y;
        x = q.front().x;
        dis = q.front().dis;
        q.pop();

        if (virus_cnt == empty_cnt) {//벽을 제외한 모든방에 바이러스가 전파
            if (MIN > time) {
                MIN = time;
            }
            return;
        }

        for (int d = 0; d < 4; d++) {
            int ny = y + dy[d];
            int nx = x + dx[d];
            if (ny<1 || nx<1 || ny>N || nx>N)continue;//연구소 사이즈를 벗어나면 pass
            if (visit[ny][nx] || map[ny][nx] == 1)continue;//이미 활성화 되었거나 벽이면 pass
            time=dis+1;
            if(map[ny][nx]==0)//전파된 바이러스의 수
                virus_cnt++;
            visit[ny][nx] = true;
            q.push(point{ ny,nx, dis + 1 });
        }
    }
}

void decide_virus(int idx, int cnt) {
    if (cnt == M) {
        spread_virus();
        return;
    }
    for (int i = idx; i < virus_pos.size(); i++) {
        virus.push_back(i);
        decide_virus(i + 1, cnt + 1);
        virus.pop_back();
    }
}

int main() {
    cin >> N >> M;
    empty_cnt = N * N;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> map[i][j];
            if (map[i][j] == 2) {//바이러스를 놓을 수 있는 위치를 저장
                virus_pos.push_back(make_pair(i, j));
            }
            else if (map[i][j] == 1) empty_cnt--;//bfs종료조건 = 전파되어야하는 바이러스의 수 = 연구소 방의개수-벽의 개수
        }
    }
    decide_virus(0, 0);

    if (MIN == MAX) {
        cout << -1;
    }
    else {
        cout << MIN;
    }
    
    return 0;
}

'알고리즘' 카테고리의 다른 글

BOJ 1946 - 신입 사원(C++)  (0) 2021.08.27
BOJ 1756 - 피자굽기(C++)  (0) 2021.08.26
Programmers - 광고삽입(C++)  (0) 2021.08.24
BOJ 1405 - 미친로봇(C++)  (0) 2021.08.24
Programmers - 외벽점검(C++)  (0) 2021.08.20

댓글