티스토리 뷰
문제 - (https://www.acmicpc.net/problem/14502)
완전탐색으로 풀 수 있는 문제였다.
세가지 스텝으로 문제를 해결할 수 있다.
1. 3개의 벽을 세울 수 있는 모든 경우를 구한다.
2. 그 상태에서 바이러스를 퍼뜨리는 시뮬레이션 진행.
3. 진행된 결과를 보고 안전 영역의 갯수를 구한다.
번호 순서대로 내 코드의 dfs, spreadVirus, dfs의 기저부분 함수를 확인하면 된다.
📌주의할 점
- 벽을 세우는 부분에서 재귀를 이용할 때, 반복문 순회에 주의하자
- 시뮬레이션을 진행할 때, deepCopy를 이용하여 새로운 배열을 만들어 진행해도 괜찮지만 굳이 그럴 필요 없이 전역으로 tempMap배열을 만들어놔서 벽이 세워진 상태의 map을 copy하는 방법을 사용하면 공간복잡도면에서 더 효율적일 수 있다.
😅실수
- 벽을 세우는 과정에서 for문을 이용해 재귀로 진입하려고 할 때, i와 j값을 인자로 넘겨주는 아래와 같은 실수를 범했다.
static void dfs(int wall, int x, int y) {
... 중략 ...
for (int i = x; i < N; i++) {
for (int j = y; j < M; j++) { /* j = y로 한 것이 실수 */
if (map[i][j] != 0) continue;
map[i][j] = 1;
dfs(wall + 1, i, j);
map[i][j] = 0;
}
}
}
- 이렇게되면 안되는 이유가, 순회할 때 j를 다 돌아서 i가 1증가하게 되면 j는 0부터 시작해야 하는데 y부터 시작하게 되버린다.
- 따라서 아래와 같이 변경해주어야 한다.
static void dfs(int wall, int x) {
... 중략 ...
for (int i = x; i < N; i++) {
for (int j = 0; j < M; j++) { /* i값 증가시 0부터 시작할 수 있도록 함 */
if (map[i][j] != 0) continue;
map[i][j] = 1;
dfs(wall + 1, i);
map[i][j] = 0;
}
}
}
- 하지만 좀 찜찜한 점이 있다.. 왜냐하면 예를들어 map[0][2]에서 재귀에 진입하면 map[0][3]부터 시작해도 되는데 굳이 map[0][0]부터 다시 시작해버린다. (물론 if문에 의해 continue되겠지만 하지않아도될 연산을 하는 거니까 찜찜하다)
- 여기서 꿀팁등장. 아래와 같은 방법으로 지금 문제를 해결할 수 있다.
for (int i = x; i < N * M; i++) {
int _x = i / M; // 행
int _y = i % M; // 열
if (map[_x][_y] == 0) {
map[_x][_y] = 1;
dfs(wall + 1, i + 1);
map[_x][_y] = 0;
}
}
- 이렇게하면, N=7,M=7이고 i가 7일때, _x=1, _y=0이므로 map[1][0]을 순회할 수 있으며 다음 재귀에서 하지 않아도될 연산을 수행하지 않게 된다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
// 골드5 - 55분
public class Laboratory {
static int N;
static int M;
static int[][] map;
static int answer = Integer.MIN_VALUE;
static ArrayList<int[]> virusPos;
static int[][] tempMap;
static int[] dx = {-1, 1, 0, 0}; // 상하좌우 이동
static int[] dy = {0, 0, -1, 1};
static void dfs(int wall, int x) {
if (wall == 3) {
// 바이러스가 퍼져나가는 것 시뮬레이션 하기
copyMap();
for (int[] virus : virusPos) {
spreadVirus(virus[0], virus[1]);
}
// 바이러스 퍼진 후의 안전 영역 크기 구하기
int safeArea = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (tempMap[i][j] == 0) safeArea += 1;
}
}
answer = Math.max(answer, safeArea);
return;
}
for (int i = x; i < N * M; i++) {
int _x = i / M;
int _y = i % M;
if (map[_x][_y] == 0) {
map[_x][_y] = 1;
dfs(wall + 1, i + 1);
map[_x][_y] = 0;
}
}
}
static void spreadVirus(int x, int y) {
// 2인 구역을 중심으로 바이러스 전염 시뮬레이션
for (int dir = 0; dir < 4; dir++) {
int moveX = x + dx[dir];
int moveY = y + dy[dir];
if (moveX < 0 || moveY < 0 || moveX >= N || moveY >= M) continue;
if (tempMap[moveX][moveY] == 0) {
tempMap[moveX][moveY] = 2;
spreadVirus(moveX, moveY);
}
}
}
static void copyMap() {
for (int i = 0; i < map.length; i++) {
tempMap[i] = map[i].clone();
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
tempMap = new int[N][M];
virusPos = new ArrayList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if (map[i][j] == 2) {
virusPos.add(new int[]{i, j});
}
}
}
dfs(0, 0);
System.out.println(answer);
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 15685번 / Java / 드래곤 커브 - 구현, 시뮬레이션 (0) | 2020.06.25 |
---|---|
[백준] 14503번 / Java / 로봇 청소기 - 구현, 시뮬레이션 (0) | 2020.06.24 |
[백준] 14891번 / Java / 톱니바퀴 - 구현, 시뮬레이션, 재귀풀이 (0) | 2020.06.23 |
[백준] 14888번 / Java / 연산자 끼워넣기 - 완전탐색, 백트래킹 (0) | 2020.06.23 |
[백준] 15684번 / Java / 사다리 조작 - DFS, 시뮬레이션, 완전탐색 풀이 (0) | 2020.06.08 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 큰 수 만들기
- 구명보트
- 14891
- 재귀
- BOJ
- dfs
- 그리디
- 우선순위큐
- 백준
- 아기상어
- java
- header
- 시뮬레이션
- 코테
- 프로그래머스
- 코딩테스트
- 사다리 조작
- 인구이동
- 구현
- 배열순회
- Access-Control-Allow-Origin
- 완전탐색
- 드래곤 커브
- 자바
- 톱니바퀴
- withCredentials
- Greedy
- 16234
- 브라우저 요청
- 코딩테스트 연습
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함