알고리즘 공부 및 문제 풀이/백준(BOJ)
[pro] 프로그래머스 level3 136797 숫자 타자 대회 (Java) - dfs, dp
yoonjiy
2022. 12. 20. 16:56
[문제]
https://school.programmers.co.kr/learn/courses/30/lessons/136797
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
[풀이]
dp를 이용해 메모이제이션 하지 않는다면 테스트케이스 후반부에 시간초과가 발생한다.
1. 먼저 0~9까지의 숫자에 대한 가중치 배열을 초기화한다. cost[i][j]에는 키패드의 숫자 i에서 j로 손가락을 움직일 경우의 가중치 값이 저장되어 있다. 같지 않고 인접하지 않는 숫자를 누를 경우, cost[i][j] = min*3 + (max-min)*2와 같이 표현할 수 있다.
2. 어떤 숫자를 눌러야 할 차례에 그 숫자 위에 올려져 있는 손가락이 있다면 반드시 그 손가락으로 눌러야 하기 때문에 이에 대한 예외처리를 해주었다.
dp[idx][left][right]에 해당 인덱스에서 left, right 위치에 있을 때의 가중치 합을 저장해주고, 만약 dp[idx][left][right]가 -1이 아니라면 이미 계산되었던 값이므로 그대로 반환한다.(메모이제이션)
[코드]
import java.util.*;
class Solution {
int[][] cost;
int[][][] dp;
int len;
String nums;
public int solution(String numbers) {
int answer = 0;
//최소한의 시간으로 타이핑을 하는 경우의 가중치 합을 return
initCost();
len = numbers.length();
nums = numbers;
dp = new int[len][10][10]; //idx, left, right
for (int i = 0; i < len; i++) {
for (int j = 0; j < 10; j++)
Arrays.fill(dp[i][j], -1);
}
return solve(0, 4, 6);
}
public int solve(int idx, int left, int right){
if(idx==len){
return 0; //문자열 끝까지 탐색한 경우
}
//이미 계산된 경우
if(dp[idx][left][right]!=-1) return dp[idx][left][right];
int num = nums.charAt(idx) - '0';
int ans = Integer.MAX_VALUE;
//왼쪽 손가락을 움직이는 경우
if(num!=right){
ans = Math.min(solve(idx+1, num, right)+cost[left][num], ans);
}
//오른쪽 손가락을 움직이는 경우
if(num!=left){
ans = Math.min(solve(idx+1, left, num)+cost[right][num], ans);
}
return dp[idx][left][right] = ans;
}
public void initCost() {
//0~9까지 가중치 배열 초기화
cost = new int[10][10];
int r1, c1, r2, c2;
for (int i = 0; i < 10; i++) {
for (int j = 0; j<10; j++) {
if(i==j){
cost[i][j] = 1;
continue;
}
if(i==0) {
r1 = 3;
c1 = 1;
}
else{
r1 = (i-1)/3;
c1 = (i-1)%3;
}
if(j==0) {
r2 = 3;
c2 = 1;
}
else{
r2 = (j-1)/3;
c2 = (j-1)%3;
}
int dr = Math.abs(r1-r2);
int dc = Math.abs(c1-c2);
int min = Math.min(dr, dc);
int max = Math.max(dr, dc);
int diff = dr+dc;
if(diff==1){
cost[i][j] = 2;
}
else if(diff>1){
cost[i][j] = min*3 + (max-min)*2;
}
}
}
}
}