codingtest

2157번 - 여행

2024-10-09
2분 분량
JAVA백준

문제 링크

문제 풀이 시간 : 1시간

문제 요약 :

  • N개의 도시 중 M개 이하의 도시를 여행한다.
  • 반드시 1번에서 시작해 N번에서 끝나야 한다.
  • 오름차순으로 이동한다.
  • 기내식 점수의 총합이 최대가 되도록 한다.

문제 풀이 :

처음에 문제를 보고 bfs인가? dp인가? 약간 고민을 했다.

근데 문제 조건에서 오름차순으로 이동해야한다는 문장이 dp 같다는 생각이 들어서 dp로 풀어보고자 했다.

처음에는 3차원 배열을 만들어서 각 비행경로와 몇번째 이동인지를 저장하려고 했다.

근데 이렇게 해도 풀수는 있을 것 같은데

대충 아래와 같은 느낌으로 4 중첩 for 문이 나왔다.

근데 저것도 조건을 다 만족하지 못해서 대략 5~6 중첩 for 문이 나올 것 같다.

java
for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                for (int l = 2; l <= m; l++) {
                    if (dp[i][j][l-1] != 0) {
                        for (int o = l; o <= n; o++) {
                            dp[i][o][l] = Math.max(dp[i][o][l], dp[i][j][l-1] + dp[j][o][l-1]);
                        }
                    }
                }
            }
        }

내가 구조를 잘못 짠 것같긴 한데.. 이런 방식으로는 못 풀 것 같다는 생각이었다.

근데 다른 풀이가 생각이 안나서 결국 다른 풀이를 참조했다.

이 문제는 dp와 bfs를 섞어서 푸는 것이었다.

dp를 2차원 배열로 현재 이동 횟수, 현재 도시 번호 로 저장을 한다.

그래서 현재 도시를 기준으로 이동할 수 있다면 해당 도시의 값을 최신화 해주는 것이다.

java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

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

        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());

        int[][] arr = new int[n + 1][n + 1];
        int[][] dp = new int[m + 1][n + 1];

        for (int i = 0; i < k; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());

            arr[a][b] = Math.max(arr[a][b], c);
        }

        Queue<Integer> q = new LinkedList<>();
        q.offer(1); //1번 도시부터 시작
        int cnt = 1; //현재 이동 횟수

        while (!q.isEmpty() && cnt<m) { //갈수있는 경로가 없거나, 이동 횟수를 초과할 때까지
            int size = q.size(); //현재 이동할 수 있는 경로

            while (size-- > 0) { 
                int now = q.poll();
                for (int i = now; i <= n; i++) {
                    if (arr[now][i] != 0) { //다음 경로가 존재하면 최신화
                        if (dp[cnt + 1][i] < dp[cnt][now] + arr[now][i]) {
                            dp[cnt+1][i] = dp[cnt][now] + arr[now][i];
                            q.offer(i);
                        }
                    }
                }
            }
            cnt++; //이동횟수 ++
        }

        int ans = 0;
        for (int i = 1; i <= m; i++) {
            ans = Math.max(ans, dp[i][n]);
        }

        System.out.println(ans);
    }
}

함께 읽으면 좋은 글

코딩 테스트2026-04-02

5430번 - AC

함수 R은 배열을 뒤집는 연산 함수 D는 첫 번째 원소를 버리는 연산 단, 배열이 비어 있을 때 D를 수행하면 error 주어진 함수 문자열을 순서대로 수행한 뒤 최종 배열을 출력하는 문제 처음에는 문제 설명 그대로 R이 나올 때마다 배열을 실제로 뒤집고, D가 나오면 맨 앞…

코딩 테스트2026-04-02

1966번 - 프린터 큐

여러 문서가 큐에 들어 있고, 각 문서마다 중요도가 있음 맨 앞 문서를 확인했을 때, 더 높은 중요도의 문서가 뒤에 하나라도 있으면 맨 뒤로 보냄 그렇지 않으면 바로 인쇄 특정 위치의 문서가 몇 번째로 인쇄되는지 구하는 문제 이 문제는 프린터의 동작을 그대로 구현하면 되는…

코딩 테스트2026-03-29

1158 - 요세푸스 문제

1번부터 N번까지 사람이 원형으로 앉아 있음 순서대로 K번째 사람을 제거 모든 사람이 제거될 때까지 반복 제거되는 순서를 출력하는 문제 이 문제는 원형으로 순회하면서 K번째를 제거하는 과정을 그대로 구현하면 된다.

코딩 테스트2026-03-29

2164번 - 카드2

1부터 N까지 카드가 순서대로 쌓여 있음 맨 위 카드를 버리고, 그다음 맨 위 카드를 맨 아래로 옮기는 과정을 반복 마지막에 남는 카드 번호를 구하는 문제 이 문제는 규칙을 찾기보다, 문제에서 하라는 과정을 그대로 구현하면 된다. 카드 더미에서 반복되는 동작은 두 가지다.