알고리즘/BOJ

[BOJ]17142번 연구소3

간타타 2020. 8. 17. 23:38

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

 

17142번: 연구소 3

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

www.acmicpc.net

아이디어

1, 활성화시킬 바이러스들을 next_permutation함수를 이용하여 택하고 bfs방법을 이용하여 퍼지는 시간을 구하였다.

 

2, 백트레킹 방식을 이용하여 탐색을 하다가 현재 구해놓은 최소 시간 이상 탐색을 실행할 시 실행을 중지하고 다음 케이스를 bfs방식으로 탐색을 하였다.

 

3, 문제의 조건에서 모든 영역에 바이러스가 있으면 종료가 됨으로(비활성화 된 바이러스도 바이러스다.) 빈칸의 수만큼 탐색을 진행할 시 탐색을 중지하고 시간을 구하였다.

 

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;

typedef struct virus {
	int r;
	int c;
	int depth;
}virus;

int N, M;

int map[51][51];
int visited[51][51];

int dr[4] = { 0,1,0,-1 };
int dc[4] = { 1,0,-1,0 };

int vector_size;

vector<virus> viruses;
vector<int> group;

int aim = 0;
int ans = 1000000;


void simulation(queue<virus> *q) {
	virus search;
	virus insert;
	int nr, nc;
	int res = 0;
	int check = 0;
	int occupy_count = 0;

	while (!q->empty()) {
		search = q->front();
		q->pop();
		

		if (occupy_count == aim) { check = 2; break; }
		
		for (int i = 0; i < 4; i++) {
			nr = search.r + dr[i];
			nc = search.c + dc[i];


			if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;


			if (map[nr][nc] != 1 && visited[nr][nc] == 0) {
				insert.r = nr;
				insert.c = nc;
				insert.depth = search.depth + 1;
				q->push(insert);
				visited[nr][nc] = 1;
				if (map[nr][nc] == 0) occupy_count++;
				if (insert.depth >= ans) { check = 1;  break; }
				else res = insert.depth;
			}
		}
		if (check == 1) break;
	}

	while (!q->empty()) {
		q->pop();
	}

	if (check == 2) {
		if (ans > res) ans = res;
	}

}

int main() {

	virus insert;
	queue<virus> q;
	scanf("%d %d", &N, &M);


	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			scanf("%d", &map[i][j]);

			if (map[i][j] == 2){
				insert.r = i;
				insert.c = j;
				insert.depth = 0;
				viruses.push_back(insert);
			}

			if (map[i][j] == 0) aim++;
						
		}
	}

	vector_size = viruses.size();


	for (int i = 0; i < vector_size; i++) {
		if (i < M) {
			group.push_back(1);
		}
		else {
			group.push_back(0);
		}
	}

	sort(group.begin(), group.end());


	do {
		
		memset(visited, 0, sizeof(visited));

		for (int i = 0; i < vector_size; i++) {
			if (group[i] == 1) {
				q.push(viruses[i]);
				visited[viruses[i].r][viruses[i].c] = 1;
			}
		}

		simulation(&q);

	} while (next_permutation(group.begin(), group.end()));

	if (ans != 1000000) {
		printf("%d\n", ans);
	}
	else {
		printf("%d\n", -1);
	}



	return 0;
}