Game Develop

[Algorithm]Baekjoon 2666번 :: 벽장문의 이동 본문

Algorithm/Baekjoon

[Algorithm]Baekjoon 2666번 :: 벽장문의 이동

MaxLevel 2024. 4. 19. 19:26

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

 

2666번: 벽장문의 이동

첫 번째 줄에 벽장의 개수를 나타내는 3보다 크고 20보다 작거나 같은 하나의 정수, 두 번째 줄에 초기에 열려있는 두 개의 벽장을 나타내는 두 개의 정수, 그리고 세 번째 줄에는 사용할 벽장들

www.acmicpc.net

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <math.h>
#include <queue>
#include <functional>
#include <sstream>
#include <memory.h>
#include <deque>
#include <set>
#include <unordered_map>
#include <stack>
#include <numeric>
 
using namespace std;
 
const int maxNum = 0x3f3f3f3f;
int wallClosetCount = 0;
int firstOpenCloset, secondOpenCloset;
int sequenceLength = 0;
int dp[21][21][21= { 0 };
int targets[21= { 0 };
 
int DFS(int left, int right, int index)
{
    if (dp[left][right][index] != maxNum) return dp[left][right][index];
    if (index == sequenceLength) return 0;
 
    int target = targets[index];
    int result = 0;
 
    if (target <= left)
    {
        result = DFS(target, right, index + 1+ left - target;
    }
    else if (target >= right)
    {
        result = DFS(left, target, index + 1+ target - right;
    }
    else
    {
        result = min(DFS(target, right, index + 1+ target - left,
                     DFS(left, target, index + 1+ right - target);
    }
 
    return dp[left][right][index] = result;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    cin >> wallClosetCount;
    cin >> firstOpenCloset >> secondOpenCloset;
    cin >> sequenceLength;
 
    for (int i = 0; i < sequenceLength; ++i)
    {
        cin >> targets[i];
    }
 
    memset(dp, 0x3fsizeof(dp));
 
    cout << DFS(firstOpenCloset, secondOpenCloset, 0);
}
cs

 

문제설명은 벽장 어쩌고저쩌고 되어있는데, 쉽게 바꾸면 처음에 두개의 포인터(왼쪽,오른쪽)가 주어지는데 주어진 타겟들을 향해 순서대로 전부 이동할 때, 최소의 이동횟수로 이동해야하는 문제이다.

 

그냥 1차원직선형태이다 보니 그냥 가장가까운 포인터가 이동하면 되지않느냐? 라고 생각할 수도 있겠지만, 예외케이스가 존재한다.

 

즉, 타겟포인터가 왼쪽과 오른쪽 사이에 있을 때이다.

타겟포인터가 왼쪽포인터이하값이라면 그냥 왼쪽포인터로 이동시키면 되고, 오른쪽포인터이상값이라면 오른쪽포인터로 이동시켜도 된다.

 

그러나 그 사이에 있다면, 반드시 두 포인터로 각각 타겟에 접근해봐야 한다.

 

dp테이블은 다음과 같다.

-> dp[왼쪽포인터][오른쪽포인터][현재 타겟인덱스]

 

ex) dp[3][5][4] == 왼쪽포인터가 3, 오른쪽포인터가 5, 현재 타겟인덱스가 4일 때, 모든 타겟들을 체크했을 때 최소값.