Algorithm/백준 문제풀이

[백준] 14728 벼락치기 - Java

너지살 2024. 4. 15. 22:33

 

 

 

문제 출저

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

 

14728번: 벼락치기

ChAOS(Chung-ang Algorithm Organization and Study) 회장이 되어 일이 많아진 준석이는 시험기간에도 일 때문에 공부를 하지 못하다가 시험 전 날이 되어버리고 말았다. 다행히도 친절하신 교수님께서 아래와

www.acmicpc.net

 

 

 

 

문제 풀이

단원의 수(n)와 공부할 수 있는 시간(t)이 주어진다. 단원은 소요된 시간(k)과 얻을 수 있는 점수(s)로 구성되어 있다. 공부할 수 있는 시간 동안 최대 점수를 구하는게 문제이다. 

 

냅색, 배낭 알고리즘으로 풀었습니다.

1차원 int 배열을 활용했습니다. 한 단원씩 탐색을 진행합니다. 현재의 점수와 단원의 시간을 뺀 점수 + 현재 단원의 점수를 비교하여 큰 값으로 업데이트 합니다. 점화식을 세우면 다음과 같습니다. 

        int[] dp = new int[t+1];
        for (int i = 1; i <= n; i++) {
            int k = board[i][0];
            int s = board[i][1];

            // 작은 것에 큰 것으로 하면 중복이 발생한다. 이를 방지하기 위해 뒤에서부터 한다
            for (int j = t; j >= k; j--) {
                dp[j] = Math.max(dp[j], dp[j-k] + s);
            }
        }

 

k부터 t까지 탐색을 진행합니다. 이 때, t부터 k까지 역순으로 진행하는데 이유는 k부터 t까지 하면 중복이 발생하여 여러 번 더할 수 있습니다. 이를 방지하기 위해 역순으로 진행합니다.

dp[t]를 출력해 정답을 나타냅니다. 

 

 

 

 

소스 코드

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


/*
벼락치지
https://www.acmicpc.net/problem/14728

2차원 배열로 k ~ t 까지 하면 k 이전의 값이 없어서 오답이 된다.
 */

public class Main {

    static int n; // 단원 개수
    static int t; // 시간
    static int[][] board;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        t = Integer.parseInt(st.nextToken());
        board = new int[n+1][2];
        for (int i = 1; i <= n; i++) {
            st = new StringTokenizer(br.readLine());
            int k = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            board[i][0] = k;
            board[i][1] = s;
        }

        int[] dp = new int[t+1];
        for (int i = 1; i <= n; i++) {
            int k = board[i][0];
            int s = board[i][1];

            // 작은 것에 큰 것으로 하면 중복이 발생한다. 이를 방지하기 위해 뒤에서부터 한다
            for (int j = t; j >= k; j--) {
                dp[j] = Math.max(dp[j], dp[j-k] + s);
            }
        }



        System.out.println(dp[t]);

    }

}