알고리즘/백준 BAEK JOON
14502.연구소
IMyoungho
2020. 5. 25. 07:09
이번 문제는 연구소이다. 꽤 많이 중요한 내용을 배우고 상기할 수 있는 문제였다.
14502번: 연구소
인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크�
www.acmicpc.net
이 문제를 푸는데 핵심은 맵을 복사해서 사용한다는 것과 나머지는 탐색이다.
난이도는 어려운 수준이 아닌 거 같지만 초보자에게 연습하기는 좋은 문제인 것 같다( 난 초보자 ㅠㅠ.. 너무좋네...)
재귀함수 관련된 문제를 조금 더 풀어봐야할 것 같다.
* 문제풀면서 중요한점
1. 문자, 특수기호 실수
=> 실수로 자꾸 if문 다음에 변수에 값을 대입할 때 "=" 대신 "=="를 사용하여 틀림 주의
=> 2중 for문 돌릴 때 변수값을 잘봐야한다 => n과 m인데 n과 n으로 처리하는 경우 주의
2. 맞다고 생각한 로직을 조심해라
=> 당연히 맞아야하는데 뭔가 원하는대로 결과가 안나올때는 구현한 로직중에 "여긴 당연히 맞았을거고, 틀린게 없어"라고
생각한 부분을 다시보거나 다시 생각해라 => 거기가 틀렸을 가능성이 제일 높다!!
3. 배열 값 실수
=> MAX 값을 너무 작게 주지 않은건 아닌지 확인해라.
=> 동적할당은 되도록이면 사용하지말자 => 실수할 수도 있고 초기화를 잘못하면 답이 꼬여버림
4. freopen은 제출할 때 주석처리 해줘야한다.
5. ++ 보다는 +=를 쓰자.
=> 이거 잘못 생각하고 처리하면 답없다..
< Code 설명 >
//#pragma warning(disable:4996)
#include <iostream>
#include <queue>
#include <algorithm>
#define MAX 9
using namespace std;
int n, m;
int map[MAX][MAX]; // map이 저장되는 공간
int c_map[MAX][MAX]; // map을 복사해서 사용할 공간(map이 변하니까)
int dx[4] = { 0, 0, 1, -1 }; //상하좌우
int dy[4] = { 1, -1, 0, 0 }; //상하좌우
int answer = 0; // 안전한구역의 최대값이 저장될 변수
queue<pair<int, int>> tmp; // virus 좌표가 저장될 큐
void copy_map(int (*a)[MAX], int(*b)[MAX]){ // 2차원 배열 복사
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
a[i][j] = b[i][j];
}
}
}
void virus_work(){ // 바이러스가 퍼짐 (BFS)
int virus_map[MAX][MAX]; //바이러스가 퍼질 맵 준비
copy_map(virus_map, c_map);//벽세운 맵을 바이러스가 퍼질맵에 복사
queue<pair<int, int>> virus;// 바이러스 좌표가 저장될 큐
virus = tmp; // 처음에 저장한 좌표를 옮김(바이러스 퍼지면 큐가 사라지기때문에)
while (!virus.empty()){
int x = virus.front().first; // x좌표
int y = virus.front().second;// y좌표 옮기고
virus.pop(); // pop 해줌
for (int i = 0; i < 4; i++){ //상하좌우 탐색
int ax = x + dx[i];
int ay = y + dy[i];
if (ax < 0 || ay < 0 || ax > n || ay > m) //맵 내에 존재해야함
continue; // 그게아니면 넘어가
if (virus_map[ax][ay] == 0){ // 안전한 공간이 있으면
virus_map[ax][ay] = 2; // 바이러스로 뒤덮음
virus.push(make_pair(ax, ay)); // 그리고 덮은 좌표들 큐에저장
}
}
}
int cnt = 0; // 안전한 공간이 cnt될 변수
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (virus_map[i][j] == 0) // 안전한 공간이 있다면
cnt += 1; // count 한다.
}
}
answer = max(answer, cnt); // 최대값 구함
}
void wall(int cnt){ // 백을 세우는 로직 (재귀함수)
if (cnt == 3){ // 탈출 구문 => 벽이 3개면
virus_work(); // 바이러스 작동
return; // 탈출
}
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (c_map[i][j] == 0){ // 안전한 공간이면
c_map[i][j] = 1; // 벽을 세움
wall(cnt + 1); // 다음벽을 세우기 위한 재귀
c_map[i][j] = 0; // 그 다음 조합을 위해 0으로 초기화
}
}
}
}
int main() {
//freopen("14502.txt", "r", stdin); // 디버깅용
cin >> n >> m;
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
cin >> map[i][j];
if (map[i][j] == 2) // 바이러스 좌표 미리 저장
tmp.push(make_pair(i, j));
}
}
copy_map(c_map, map); // 맵을 복사함
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (map[i][j] == 0){ // 0일 경우
c_map[i][j] = 1; // 벽을 세움
wall(1); // 하나 세웠으니까 1로시작
c_map[i][j] = 0; // 다음 조합을 위해 0으로 초기화
}
}
}
cout << answer << "\n";
return 0;
}
반응형