ps

[백준] 2342 - Dance Dance Revolution

kariskan 2022. 8. 17. 16:18

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

 

2342번: Dance Dance Revolution

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

www.acmicpc.net

 

현재 발의 위치와 이동할 발의 위치에 따라 사용되는 힘이 달라지고,

주어진 수열에 적절히 발을 움직여 사용하는 최소 힘을 구하는 문제이다.

 

왼발, 오른발이 있으므로 모든 경우의 수를 따져보면 2^N, TLE가 날 것이다.

그리디도 생각을 했지만, 반례가 바로 떠올랐고 따라서 dp로 해결하였다.

 

dp[i][j][k] = i번째 행동을 j, k 위치의 발로 눌렀을 때 최소의 힘이라 정의하였다.

그러고 top-down 방식으로 진행하였다.

 

정말 단순하게 왼발을 움직였을 때와 오른발을 움직였을 때를 구분하여 최솟값으로 dp배열을 갱신하면 된다.

 

왼발을 움직였을 때 => go(n + 1, a[n], j) + getStrength(i, a[n])

오른발을 움직였을 때 => go(n + 1, i, a[n]) + getStrength(i, a[n])

 

#include <iostream>
using namespace std;

int a[100000], dp[100000][5][5], idx; //i번째 수열을 j, k 위치의 발로 눌렀을 때 최소 힘

int getStrength(int i, int j) {
	if (i == j) return 1;
	if ((i == 1 && j == 3) || (i == 2 && j == 4) || (i == 3 && j == 1) || (i == 4 && j == 2)) return 4;
	if (i == 0 || j == 0) return 2;
	return 3;
}

int go(int n, int i, int j) {

	if (idx == n) return 0;

	if (dp[n][i][j])return dp[n][i][j];

	int ret = min(go(n + 1, i, a[n]) + getStrength(j, a[n]), go(n + 1, a[n], j) + getStrength(i, a[n]));

	return dp[n][i][j] = ret;
}

int main() {

	while (1) {
		int n;
		cin >> n;
		if (n == 0)break;
		a[idx++] = n;
	}

	cout << go(0, 0, 0);

	return 0;
}