알고리즘 문제풀이

[BOJ] 2342 - Dance Dance Revolution 본문

자료구조 + 알고리즘/[BOJ]

[BOJ] 2342 - Dance Dance Revolution

JoonDev 2021. 6. 3. 18:50

2342번 - Dance Dance Revolution

시간제한 메모리 제한 제출 정답 맞은 사람 정답 비율
2 초 128 MB 4785 1632 1194 35.856%

문제

승환이는 요즘 "Dance Dance Revolution"이라는 게임에 빠져 살고 있다. 하지만 그의 춤 솜씨를 보면 알 수 있듯이, 그는 DDR을 잘 하지 못한다. 그럼에도 불구하고 그는 살을 뺄 수 있다는 일념으로 DDR을 즐긴다.

DDR은 아래의 그림과 같은 모양의 발판이 있고, 주어진 스텝에 맞춰 나가는 게임이다. 발판은 하나의 중점을 기준으로 위, 아래, 왼쪽, 오른쪽으로 연결되어 있다. 편의상 중점을 0, 위를 1, 왼쪽을 2, 아래를 3, 오른쪽을 4라고 정하자.

처음에 게이머는 두 발을 중앙에 모으고 있다.(그림에서 0의 위치) 그리고 게임이 시작하면, 지시에 따라 왼쪽 또는 오른쪽 발을 움직인다. 하지만 그의 두 발이 동시에 움직이지는 않는다.

이 게임에는 이상한 규칙이 더 있다. 두 발이 같은 지점에 있는 것이 허락되지 않는 것이다. (물론 게임 시작시에는 예외이다) 만약, 한 발이 1의 위치에 있고, 다른 한 발이 3의 위치에 있을 때, 3을 연속으로 눌러야 한다면, 3의 위치에 있는 발로 반복해야 눌러야 한다는 것이다.

오랫동안 DDR을 해 온 백승환은 발이 움직이는 위치에 따라서 드는 힘이 다르다는 것을 알게 되었다. 만약, 중앙에 있던 발이 다른 지점으로 움직일 때, 2의 힘을 사용하게 된다. 그리고 다른 지점에서 인접한 지점으로 움직일 때는 3의 힘을 사용하게 된다. (예를 들면 왼쪽에서 위나 아래로 이동할 때의 이야기이다.) 그리고 반대편으로 움직일때는 4의 힘을 사용하게 된다. (위쪽에서 아래쪽으로, 또는 오른쪽에서 왼쪽으로). 만약 같은 지점을 한번 더 누른다면, 그때는 1의 힘을 사용하게 된다.

만약 1 → 2 → 2 → 4를 눌러야 한다고 가정해 보자. 당신의 두 발은 처음에 (point 0, point 0)에 위치하여 있을 것이다. 그리고 (0, 0) → (0, 1) → (2, 1) → (2, 1) → (2, 4)로 이동하면, 당신은 8의 힘을 사용하게 된다. 다른 방법으로 발을 움직이려고 해도, 당신은 8의 힘보다 더 적게 힘을 사용해서 1 → 2 → 2 → 4를 누를 수는 없을 것이다.

입력

입력은 지시 사항으로 이루어진다. 각각의 지시 사항은 하나의 수열로 이루어진다. 각각의 수열은 1, 2, 3, 4의 숫자들로 이루어지고, 이 숫자들은 각각의 방향을 나타낸다. 그리고 0은 수열의 마지막을 의미한다. 즉, 입력 파일의 마지막에는 0이 입력된다. 입력되는 수열의 길이는 100,000을 넘지 않는다.

출력

한 줄에 모든 지시 사항을 만족하는 데 사용되는 최소의 힘을 출력한다.


예제 입력 1

1 2 2 4 0

예제 출력 1

8

 

출처

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

 

2342번: Dance Dance Revolution

입력은 지시 사항으로 이루어진다. 각각의 지시 사항은 하나의 수열로 이루어진다. 각각의 수열은 1, 2, 3, 4의 숫자들로 이루어지고, 이 숫자들은 각각의 방향을 나타낸다. 그리고 0은 수열의 마

www.acmicpc.net

알고리즘 분류

  • 다이나믹 프로그래밍

접근 방법

만약 우리가 도달하고 싶은 영역이 4라고 생각을 해보자.

해당 영역에 도달할 수 있는 방법은 이전까지 밟고 온 영역에서 오른발을 옮겨 4에 도달하거나, 왼발을 옮겨 4에 도달한 것이라 생각할 수 있다. 우리가 구하고자 하는 것은 이 영역에 도달하는데 필요한 최소 힘이므로 ${min( [i][j], i != j ) }$ 이라고 생각할 수 있겠다.

그렇다면, 이전까지 요구조건을 만족하고 현재 발의 위치가 [left][right] 일 때 현재 요구조건(K)에 대해서 구하려고 한다면, 

left가 존재할 수 있는 위치와 right가 존재할 수 있는 위치 각각에 대하여 연산한 후 최솟값을 저장하면 되겠다.

단 처음을 제외한 이 후 조건에서 left != right 라는 조건이 붙지만, 상식적으로 같은 곳을 밟는 경우 코스트가 1이고 다른 위치에서 또 다른 위치로 발을 옮기는데 필요한 코스트가 2이상이므로 예외처리를 할 필요가 없다.

 

dp table을 다음과 같이 정의해보자.

dp[s][i][j] : s번째 요구조건 까지 만족하고 왼쪽 발(i), 오른쪽 발(j)에 위치 할 경우 최소 힘

그러면 점화식은 다음과 같이 세울 수 있을 것이다.

 

( current 는 s+1번째 요구조건 )
( cost[a][b] : a위치에서 b위치까지 움직이는데 필요한 최소 힘 ) 

dp[s+1][i][ current ] = dp[s][i][j] + cost[j][current] 

dp[s+1][current][i] = dp[s][i][j] + cost[i][current]

 


소스 코드

#include <bits/stdc++.h>
using namespace std;
vector<int> v;
int cost[5][5] ={
    //   0  1  2  3  4
        {1, 2, 2, 2, 2},
        {3, 1, 3, 4, 3},
        {3, 3, 1, 3, 4},
        {3, 4, 3, 1, 3},
        {3, 3, 4, 3, 1}
};
int dp[100001][5][5] ;
int main(void){
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);


    while(true){
        int in;
        cin >> in;
        if( in == 0 )
            break;
        v.push_back(in);
    }

    // dp[st][i][j] : st번째까지 지시 사항을 만족했을 때, (i,j) 위치에 서있는 최소 힘.
    for(int i=0; i<100001; i++){
        for(int j=0; j<5; j++)
            fill(dp[i][j], dp[i][j] + 5, 1e9);
    }

    dp[0][0][0] = 0;
    for(int st = 1; st <= v.size(); st++){
        int current = v[st-1];
        for(int i=0; i<5; i++){
            for(int j=0; j<5; j++){
                dp[st][i][current] = min(dp[st][i][current], dp[st-1][i][j] + cost[j][current] );
            }
        }
        for(int i=0; i<5; i++){
            for(int j=0; j<5; j++){
                dp[st][current][i] = min(dp[st][current][i], dp[st-1][i][j] + cost[j][current] );
            }
        }
    }

    int ans = 1e9;
    for(int i=0; i<5; i++){
        for(int j=0; j<5; j++){
            if( ans > dp[v.size()][i][j] )
                ans = dp[v.size()][i][j];
        }
    }
    cout << ans ;

    return 0;
}

 

'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글

[BOJ] 12969번 - ABC  (2) 2021.07.21
[BOJ] 2151번 - 거울 설치  (0) 2021.07.12
[BOJ] 10090 번 - Counting Inversions  (0) 2021.05.29
[BOJ] 1208번 - 부분수열의 합 2  (0) 2021.04.28
[BOJ] 1202번 - 보석 도둑  (0) 2021.04.27
Comments