반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- 원금리스크
- 백준 파티
- 행크TV
- 매일경제
- 자발적 실업
- 부동산 기사읽기
- 경제 기사읽기
- KFO
- 엥겔의법칙
- 제로금리정책
- 특수목적기구
- 웅덩이 매매법
- 월부TV
- 유전자오작동
- 급여액
- 부동산기사읽기
- 이중통화채(dual currency bond)
- 경제기사 읽기
- 백준 1238
- 자의식 해체
- 연방준비제도(FRS)/연방준비은행(FRB)
- 경제적 자유를 위한 5가지 공부법
- 평균급여액
- 한국직업개발원
- 정체성 만들기
- 경제금융용어
- 구해줘월부
- 업무지구별
- 역행자
- 황농문 서울대교수
Archives
- Today
- Total
록키의 No Pain, No Gain
[BOJ] 17142번 연구소 3 본문
반응형
https://www.acmicpc.net/problem/17142
17142번: 연구소 3
인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고, 활성 상태인 바이러스는 상하좌우로 인접한 모든 빈 칸으로 동시에 복제되며, 1초가 걸린다. 승원이는 연구소의 바이러스 M개를 활성 상태로 변경하려고 한다. 연구소는 크기가 N×N인 정사각형으로 나타낼 수 있으며, 정사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는
www.acmicpc.net
이 문제는 작년 상반기 삼성전자 인턴때 풀었던 것으로 기억나는 데, 그 때 바이러스가 이미 있는 부분에 대해서 시간을 체크해서 그거 찾느라 시간이 오래 걸렸었다. 문제를 잘 읽었으면 그런 일은....
문제
바이러스 중 M개를 활성화 시켜서, 모든 빈칸에 바이러스를 퍼뜨리는 최단 시간을 구하는 것이다
풀이
이 문제는 BackTracking + BFS를 이용하고 약간의 조건들을 생각해 주어야 하는 전형적인 삼성 A형 문제이다.
- 우선, 바이러스 중 M개를 선택한다. (BackTraking, 조합)
- 그 다음, 모든 빈칸에 바이러스를 퍼뜨린다. (BFS) 주의해야 할 점은 바이러스를 퍼뜨릴 때, 이미 빈칸에 바이러스가 모두 퍼진 경우 퍼뜨리는 동작을 끝내야 한다. 계속 퍼뜨리면서 시간을 증가시켜 주면 안된다..
실수 했던 부분
- 같은 실수를 했다....
- 그리고 j를 i로 잘못써서 무한루프 도는 실수를 했다. 집중 안하면 생기는 실수..
//연구소의 바이러스 M개 활성상태로 변경
//활성 바이러스가 비활성 바이러스가 있는 칸으로 가면 비활성 바이러스가 활성으로 변함
//모든 빈 칸에 바이러스를 퍼뜨리는 최소 시간을 구하기
//만약 모든 빈칸에 바이러스를 못 퍼뜨리면 -1 출력
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
using namespace std;
int N, M, answer, cnt;
int map[51][51];
bool visited[51][51];
pair<int, int> selected[10];
int dy[4] = { -1,1,0,0 };
int dx[4] = { 0,0,-1,1 };
vector<pair<int, int>> virus;
int bfs(int cnt) {
//활성된 바이러스들 큐에 넣어준다.
queue<pair<int, int>> q;
for (int i = 0; i < M; i++) {
q.push(selected[i]);
visited[selected[i].first][selected[i].second] = true;
}
int t = -1;
while (!q.empty()) {
t++;
//모든 빈칸에 바이러스를 퍼뜨린 경우
if (cnt == 0) {
break;
}
int sz = q.size();
for (int i = 0; i < sz; i++) {
int cy = q.front().first;
int cx = q.front().second;
q.pop();
for (int j = 0; j < 4; j++) {
int ny = cy + dy[j];
int nx = cx + dx[j];
if (ny <= 0 || nx <= 0 || ny > N || nx > N) continue;
if (map[ny][nx] == 1) continue;
if (visited[ny][nx]) continue;
if (map[ny][nx] == 0) cnt--;
q.push({ ny,nx });
visited[ny][nx] = true;
}
}
}
if (cnt != 0) t = 2500;
return t;
}
void init() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
visited[i][j] = false;
}
}
}
void dfs(int depth, int start) {
//M개를 뽑은 경우
if (depth == M) {
init();
answer = min(answer, bfs(cnt));
return;
}
for (int i = start; i < virus.size(); i++) {
selected[depth] = virus[i];
dfs(depth + 1, i + 1);
}
}
int main() {
answer = 2500;
cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cin >> map[i][j];
if (map[i][j] == 0) cnt++;
if (map[i][j] == 2) virus.push_back({ i,j });
}
}
//빈칸이 없는 경우
if (cnt == 0) {
cout << 0;
return 0;
}
//M개를 뽑는다.
dfs(0, 0);
if (answer == 2500) cout << -1;
else cout << answer;
return 0;
}
반응형
'알고리즘' 카테고리의 다른 글
[BOJ] 17471번 게리멘더링 (0) | 2020.04.28 |
---|---|
[BOJ] 17822번 원판 돌리기 (0) | 2020.04.28 |
[BOJ] 17825 주사위 윷놀이 (0) | 2020.04.28 |
[BOJ] 16895번 Maaaaaaaaaze (0) | 2020.04.25 |
[BOJ] 18809 Gaaaaaaaaaarden (0) | 2020.04.21 |
Comments