[백준] 2342 - Dance Dance Revolution

2021. 7. 9. 22:03·알고리즘 (PS)/BOJ
반응형

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

 

2342번: Dance Dance Revolution

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

www.acmicpc.net

solved.ac의 class5 문제를 보던 중 시도해보게 된 DP 문제 Dance Dance Revolution의 풀이과정을 정리한다.

매우 비효율적으로 풀게 되었지만, 우선은 3차원 DP테이블로 DP문제를 푸는 경험을 해봤다는 것으로 만족하고자 한다.

 

이 문제를 보고 제일 먼저 떠오른 풀이는 그리디하게 매 순간 가장 가까운 위치의 버튼을 누르는 것이었지만,

지금 당장 누르지 않고 참았다가 다른 것을 누르는 것이 더 효율적일 때도 있다.

 

1 3 2 4 1 2 0

라는 예시가 있을 때,

맨 처음 2를 누른 발은 마지막 2를 누르기 위해 기다려야만 최적해인 14의 힘으로 버튼을 누를 수 있다.

 

이때 주어지는 수열의 길이가 최대 10만으로 다소 작은 사이즈인 점을 고려해볼 때

DP로 풀면 풀릴 것 같다는 느낌은 바로 받을 수 있었다.


풀이 아이디어

이제 점화식을 세우는 것이 관건인데 왼발과 오른발을 모두 고려하여야하고,

각 발이 마지막으로 누른 위치에 따라 다음 위치를 누를 때 추가되는 점수가 다른 점에서

왼발과 오른발 각각이 마지막으로 누른 버튼위치에 따른 점수를 기록하면 되겠다는 아이디어를 떠올렸다.

 

그래서 dp테이블은 다음과 같이 구성하였고

dp[현재 스탭 인덱스][왼발최종위치][오른발최종위치]

 

점화식은 다음과 같이 구성하였다.

dp[현재 스탭 인덱스][왼발최종위치][오른발최종위치] =

dp[직전 스탭 인덱스][왼발최종위치]오른발최종위치] + 이동하여 버튼을 누르는데 든 힘

 

만약 1을 누를 차례라면

dp[현재스탭인덱스][1][직전 오른발최종위치]

dp[현재스탭인덱스][직전 왼발최종위치][1]

이 두가지를 각각 구하여 저장해두면 된다.


최종 코드

# 2342 Dance Dance Revolution
seq = list(map(int, input().split()))
seq = [0] + seq
dp = [[[500000 for _ in range(5)] for __ in range(5)] for ___ in range(len(seq))]
dp[0][0][0] = 0

for i in range(1, len(seq)):
    if seq[i] == 0:  # print answer
        answer = 500000
        for left in range(5):
            for right in range(5):
                if left == right:
                    continue
                if dp[i-1][left][right] == -1:
                    continue
                if left == seq[i-1] or right == seq[i-1]:
                    answer = min(answer, dp[i-1][left][right])
        print(0 if answer == 500000 else answer)
        break

    now_step = seq[i]

    for left in range(5):
        for right in range(5):
            if dp[i-1][left][right] == -1:
                continue

            if left != now_step: # 왼발은 고정시키고, 오른발을 now_step으로 이동시키는 경우
                if right == 0:
                    dp[i][left][now_step] = min(dp[i][left][now_step], dp[i-1][left][right] + 2)
                elif abs(now_step - right) == 0: # 같은 위치를 밟는 경우
                    dp[i][left][now_step] = min(dp[i][left][now_step], dp[i-1][left][right] + 1)
                elif abs(now_step - right) == 1 or abs(now_step - right) == 3: # 인접한 곳을 밟는 경우
                    dp[i][left][now_step] = min(dp[i][left][now_step], dp[i-1][left][right] + 3)
                elif abs(now_step - right) == 2: #  반대편으로 움직이는 경우
                    dp[i][left][now_step] = min(dp[i][left][now_step], dp[i-1][left][right] + 4)

            if right != now_step:  # 오른발은 고정시키고, 왼발을 now_step으로 이동시키는 경우
                if left == 0:
                    dp[i][now_step][right] = min(dp[i][now_step][right], dp[i - 1][left][right] + 2)
                elif abs(now_step - left) == 0:  # 같은 위치를 밟는 경우
                    dp[i][now_step][right] = min(dp[i][now_step][right], dp[i - 1][left][right] + 1)
                elif abs(now_step - left) == 1 or abs(now_step - left) == 3:  # 인접한 곳을 밟는 경우
                    dp[i][now_step][right] = min(dp[i][now_step][right], dp[i - 1][left][right] + 3)
                elif abs(now_step - left) == 2:  # 반대편으로 움직이는 경우
                    dp[i][now_step][right] = min(dp[i][now_step][right], dp[i - 1][left][right] + 4)

이 코드의 dp 테이블을 출력해보면

왼발, 오른발로 구성된 2차원 행렬이 대각선 대칭임을 알 수 있다.

이는 첫 발을 밟을 때, 왼발을 먼저 밟든 오른발을 먼저 밟든 상관이 없는데,

이 코드에서는 둘을 구분하여 저장하기 때문에 생기는 문제이다.

만약 첫 발 한정으로 왼발 오른발을 구분하지 않는다면 시간효율이 더 좋아질 것으로 생각된다.

반응형
저작자표시 비영리 변경금지 (새창열림)

'알고리즘 (PS) > BOJ' 카테고리의 다른 글

[백준] 2437 - 저울  (0) 2021.07.17
[백준] 15815 - 천재 수학자 성필  (0) 2021.07.10
[백준] 1918 - 후위 표기식  (0) 2021.07.04
[백준] 3709 - 레이저빔은 어디로  (0) 2021.07.02
[백준] 1043 - 거짓말 (분리집합 풀이)  (0) 2021.06.30
'알고리즘 (PS)/BOJ' 카테고리의 다른 글
  • [백준] 2437 - 저울
  • [백준] 15815 - 천재 수학자 성필
  • [백준] 1918 - 후위 표기식
  • [백준] 3709 - 레이저빔은 어디로
에버듀
에버듀
개발은 좋은데 뭘로 개발할까
  • 에버듀
    Blog. 에버듀
    에버듀
  • 전체
    오늘
    어제
    • 분류 전체보기 (615) N
      • 개인 프로젝트 (43)
        • 토이 프로젝트 (3)
        • [2020] 카카오톡 봇 (9)
        • [2021] 코드악보 공유APP (22)
        • [2022] 유튜브 뮤직 클론코딩 (9)
        • [2025] 한글 SQL 데이터베이스 (0)
      • 팀 프로젝트 (22)
        • [2020] 인공지능 숫자야구 (4)
        • [2022] OSAM 온라인 해커톤 (10)
        • [2024] GDSC 프로젝트 트랙 (6)
        • [2025] 큰소리 웹 페이지 (2)
      • CS (335)
        • 자료구조 (19)
        • 어셈블리 (41)
        • 멀티미디어응용수학 (7)
        • 컴퓨터 구조 (29)
        • 알고리즘 분석 (4)
        • 컴퓨터 네트워크 (38)
        • 프로그래밍언어론 (15)
        • HCI 윈도우즈프로그래밍 (26)
        • 기초데이터베이스 (29)
        • 운영체제 (23)
        • 오토마타 (24)
        • 문제해결기법 (11)
        • 블록체인 (22)
        • 소프트웨어공학 (21)
        • 기계학습심화 (12)
        • 컴퓨터그래픽스와 메타버스 (8)
        • 분산시스템특론 (6)
      • 자기계발 (45) N
        • 생각 정리 (23) N
        • 대외활동 (11)
        • 동아리 (7)
        • 자격증 (3)
        • 머니 스터디 (1)
      • 알고리즘 (PS) (107)
        • BOJ (101)
        • Programmers (5)
        • 알고리즘 이모저모 (1)
      • WEB(BE) (8)
        • express.js (1)
        • Spring & Spring Boot (7)
      • WEB(FE) (2)
        • html, css, js (1)
        • React.js (1)
      • Tool & Language (6)
        • Edit Plus (1)
        • Git (1)
        • Python3 (2)
        • Java (2)
      • Infra (12)
        • AWS (1)
        • Oracle Cloud (8)
        • Firebase (2)
        • Network (1)
      • Android (18)
        • Java (6)
        • Flutter (12)
      • Window (2)
        • Visual Studio 없이 WPF (1)
        • MFC (1)
      • 독서 (14)
        • Inside Javascript (7)
        • Database Internals (6)
        • 한 글 후기 (1)
  • 링크

    • github
    • website
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
에버듀
[백준] 2342 - Dance Dance Revolution
상단으로

티스토리툴바