SY 개발일지
article thumbnail

문제 링크: https://www.acmicpc.net/problem/17485

 

1. 문제

우주비행이 꿈이였던 진우는 음식점 '매일매일싱싱'에서 열심히 일한 결과 달 여행에 필요한 자금을 모두 마련하였다! 지구와 우주사이는 N X M 행렬로 나타낼 수 있으며 각 원소의 값은 우주선이 그 공간을 지날 때 소모되는 연료의 양이다.

[예시]

진우는 여행경비를 아끼기 위해 조금 특이한 우주선을 선택하였다. 진우가 선택한 우주선의 특징은 아래와 같다.

1. 지구 -> 달로 가는 경우 우주선이 움직일 수 있는 방향은 아래와 같다.

2. 우주선은 전에 움직인 방향으로 움직일 수 없다. 즉, 같은 방향으로 두번 연속으로 움직일 수 없다.

진우의 목표는 연료를 최대한 아끼며 지구의 어느위치에서든 출발하여 달의 어느위치든 착륙하는 것이다.

최대한 돈을 아끼고 살아서 달에 도착하고 싶은 진우를 위해 달에 도달하기 위해 필요한 연료의 최소값을 계산해 주자.

 

2. 입력

첫줄에 지구와 달 사이 공간을 나타내는 행렬의 크기를 나타내는 N, M (2 ≤ N, M ≤ 1000)이 주어진다.

다음 N줄 동안 각 행렬의 원소 값이 주어진다. 각 행렬의 원소값은 100 이하의 자연수이다.

 

3. 출력

달 여행에 필요한 최소 연료의 값을 출력한다.

 

4. 풀이

4.1. 접근법

  1. 전형적인 DP 문제이다.
  2. 같은 방향으로 두번 연속 움직이지 못하니까, 이 값을 미리 저장해두고 다른 방향에서 오는 것 중 최소값을 넣으면 될 것 같다.
  3. 값이 최대 100,000,000을 넘지 않는 정수 범위니까, DP 배열을 이보다 크게 두고, 최소값만 가져온다면 코드를 더 간결하게 작성할 수 있을 것 같다.
  4. 지구 어디서든 출발하여 달 어디든 착륙하니까 마지막 행의 값들 중 최소값이 연료의 최솟값이 될 것이다.

 

4.2. 코드

<java />
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; 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[][] arr = new int[N][M]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); for(int j=0;j<M;j++) arr[i][j] = Integer.parseInt(st.nextToken()); } // 1. 전형적인 DP 문제이다. int[][][] dp = new int[3][N][M]; // 3. 값이 최대 100,000,000을 넘지 않는 정수 범위니까, DP 배열을 이보다 크게 두고, // 최소값만 가져온다면 코드를 더 간결하게 작성할 수 있을 것 같다. for(int k=0;k<3;k++) for(int i=0;i<N;i++) Arrays.fill(dp[k][i], 1000000000); int[] dy = {-1, 1, 0}; for(int j=0;j<M;j++) { for(int k=0;k<3;k++) dp[k][0][j] = arr[0][j]; } for(int i=1;i<N;i++) { for(int j=0;j<M;j++) { // 2. 같은 방향으로 두번 연속 움직이지 못하니까, // 이 값을 미리 저장해두고 다른 방향에서 오는 것 중 최소값을 넣으면 될 것 같다. for(int k=0;k<3;k++) { int ny = j + dy[k]; if (ny < 0 || ny >= M) continue; // 범위 체크 for(int m=0;m<3;m++) { if (k == m) continue; // 같은 방향에서 올 수 없음 dp[k][i][j] = Math.min(dp[k][i][j], dp[m][i-1][ny] + arr[i][j]); } } } } // 4. 지구 어디서든 출발하여 달 어디든 착륙하니까 마지막 행의 값들 중 최소값이 연료의 최솟값이 될 것이다. int ans = 1000000000; for(int j=0;j<M;j++) { for(int k=0;k<3;k++) { ans = Math.min(ans, dp[k][N-1][j]); } } System.out.println(ans); } }

 

14분 걸렸다 !

profile

SY 개발일지

@SY 키키

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!