Algorithm/DP

BOJ#2666 벽장문의 이동

밤이2209 2017. 4. 8. 15:15

BOJ#2666 벽장문의 이동


* 문제


* 풀이

1. 문제 이해
벽장문을 이동을 열려있는 문이 이동한다는 것으로 바꿔서 생각해봅시다. 훨씬 편하게 문제를 이해할 수 있습니다.
열려있는 문은 항상 2개 뿐이므로 하나를 F, 나머지를 S라고 해봅시다.

열려있는 문이 이동하므로 2가지 경우가 발생합니다. 
1) F가 이동하는 경우
2) S가 이동하는 경우

2. 풀이 설계
이 문제는 벽장문의 사용 순서에 따라 탐색이 진행되고, 완전 탐색이 되어야 합니다.
이 과정에서 필요한 것, 저장시켜야 하는 것, 변화하는 것들을 이용하여 dp를 정의하고 점화식을 세워보면

(정의)
dp[pos1][pos2][idx] : 열린문 F의 위치가 pos1이고 열린문 S의 위치가 pos2 그리고 현재 탐색 위치가 idx일 때, 벽장문을 모두 사용하는데 필요한 최소 이동의 수

(점화식)
dp[pos1][pos2][idx] = min(열린문 F가 이동하는 경우, 열린문 S가 이동하는 경우)


* 나의 코드


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
* BOJ#2666 벽장문의 이동
* https://www.acmicpc.net/problem/2666
*/

public class Main {

static int n; // 벽장의 개수
static int m; // 사용할 벽장의 개수
static int[] opened = new int[2];
static int[] order;

// dp[pos1][pos2][depth] : 열린문이 pos1, pos2에 위치하고 사용한 벽장문의 개수가 idx일때, 벽장문을 모두 사용하는데 필요한 최소 이동 수
static int[][][] dp = new int[21][21][21];

static final int NOT_VISITED = -1;

static {

for (int i = 0; i < 21; i++) {
for (int j = 0; j < 21; j++) {

Arrays.fill(dp[i][j], NOT_VISITED);
}
}
}

public static void main(String[] args) throws IOException {

// input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

n = Integer.parseInt(br.readLine());

StringTokenizer st = new StringTokenizer(br.readLine());

opened[0] = Integer.parseInt(st.nextToken());
opened[1] = Integer.parseInt(st.nextToken());

m = Integer.parseInt(br.readLine());
order = new int[m];
for (int i = 0; i < m; i++) {

order[i] = Integer.parseInt(br.readLine());
}

// solve
System.out.println(solve(opened[0], opened[1], 0));
}

static int solve(int firstPos, int secondPos, int idx) {

// 기저 조건
if (idx == m) {

return 0;
}

// memoization
if (dp[firstPos][secondPos][idx] != NOT_VISITED) return dp[firstPos][secondPos][idx];

// 탐색
dp[firstPos][secondPos][idx] = Math.min(solve(order[idx], secondPos, idx + 1) + Math.abs((order[idx] - firstPos)),
solve(firstPos, order[idx], idx + 1) + Math.abs((order[idx] - secondPos)));

return dp[firstPos][secondPos][idx];
}
}



'Algorithm > DP' 카테고리의 다른 글

BOJ#14501 퇴사  (0) 2017.04.22
BOJ#1937 욕심쟁이 판다  (0) 2017.04.12
BOJ#5557 1학년  (0) 2017.04.08
BOJ#2098 외판원 순회  (0) 2017.04.07
BOJ#9520 NP-Hard  (0) 2017.04.06