코딩 테스트/BAEKJOON

[Java] 12026 BOJ 거리

에이디/김우진 2024. 4. 15. 14:53

문제

문제
BOJ 거리는 보도블록 N개가 일렬로 놓여진 형태의 도로이다. 
도로의 보도블록은 1번부터 N번까지 번호가 매겨져 있다.

스타트의 집은 1번에 있고, 링크의 집은 N번에 있다.
스타트는 링크를 만나기 위해서 점프해가려고 한다.

BOJ거리의 각 보도블록에는 B, O, J 중에 하나가 쓰여 있다.
1번은 반드시 B이다.

스타트는 점프를 통해서 다른 보도블록으로 이동할 수 있다.
이때, 항상 번호가 증가하는 방향으로 점프를 해야 한다. 
만약, 스타트가 현재 있는 곳이 i번이라면, i+1번부터 N번까지로 점프를 할 수 있다.

한 번 k칸 만큼 점프를 하는데 필요한 에너지의 양은 k*k이다.

스타트는 BOJ를 외치면서 링크를 만나러 가려고 한다. 
따라서, 스타트는 B, O, J, B, O, J, B, O, J, ... 순서로 보도블록을 밟으면서 점프를 할 것이다.

스타트가 링크를 만나는데 필요한 에너지 양의 최솟값을 구하는 프로그램을 작성하시오.

입력
첫째 줄에 1 ≤ N ≤ 1,000이 주어진다.

둘째 줄에는 보도블록에 쓰여 있는 글자가 1번부터 순서대로 주어진다.

출력
스타트가 링크를 만나는데 필요한 에너지 양의 최솟값을 출력한다. 
만약, 스타트가 링크를 만날 수 없는 경우에는 -1을 출력한다.

문제 풀이

DP문제이다.

처음에는 그냥 idx 한 칸 씩  진행하면서 다음 단어인지 확인하면서 넘어가면 될거 같았는데 문제가 많았다.

시간도 2초로 적당하고 n의 수도 1000정도로 낮아서 이중 FOR문으로 하나씩 검사하면서 해당 칸에 도달하는 가장 작은 에너지 값을 저장해가면 충분히 가능할 것 같았다.

 

해당 칸에 도달하기 위한 최소 에너지를 기록하기 위한 dp 배열을 하나 만들고 Integer.MAX_VALUE로 채운다.

i = 1 칸부터 시작하여 해당 i칸에 도달하기 위한 가장 적은 에너지를 계산한다. j = 0부터 i전까지의 칸에서 i칸 전 단어가 기록된 칸을 기준으로 현 i칸의 에너지와 j칸 + i-j의 2제곱 한 값 중 작은 값을 계속 i칸에 갱신해가면서 계산한다.

 

이후 가장 마지막칸의 에너지 값을 출력한다.

자바 코드

import java.util.*;
import java.io.*;
import java.math.*;

public class BOJ {
	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		char[] arr = br.readLine().toCharArray();
		int[] dp = new int[N];
		Arrays.fill(dp, Integer.MAX_VALUE);
		dp[0] = 0;
		for (int i = 1; i < dp.length; i++) {
			for (int j = 0; j < i; j++) {
				if(arr[i] == 'O' && arr[j] == 'B' && dp[j] != Integer.MAX_VALUE) {
					dp[i] = Math.min(dp[i], dp[j] + (i-j)*(i-j));
				}
				else if(arr[i] == 'J' && arr[j] == 'O' && dp[j] != Integer.MAX_VALUE) {
					dp[i] = Math.min(dp[i], dp[j] + (i-j)*(i-j));
				}
				else if(arr[i] == 'B' && arr[j] == 'J' && dp[j] != Integer.MAX_VALUE) {
					dp[i] = Math.min(dp[i], dp[j] + (i-j)*(i-j));
				}
				
			}
		}
		System.out.println((dp[N-1]==Integer.MAX_VALUE)?-1:dp[N-1]);
	}

}

 

이전 실패 코드

더보기

시간 초과

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class BOJ {
    private static int N;
    private static String[] block;
    private static int result = Integer.MAX_VALUE;
    private static final String[] pointer = {"B", "O", "J"};
    private static int idx = 1;
    private static boolean flag = false;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());
        block = br.readLine().split("");

        go(0, 0);

        if(flag)
            System.out.println(result);
        else
            System.out.println(-1);
    }

    private static void go(int depth, int energy){
        if(depth == N - 1){
            flag = true;
            result = Math.min(result, energy);
            return;
        }

        if(energy > result)
            return;

        if(result < N){
            System.out.println(result);
            System.exit(1);
        }

        for(int i = depth + 1; i < N; i++){
            if(!pointer[idx].equals(block[i])) {
                continue;
            }

                idx = (idx + 1) % 3;
                go(i, energy + (int) Math.pow(i - depth, 2));
                idx = (idx + 2) % 3;
        }
    }
}