본문 바로가기

Algorithm/Inflearn

[Inflearn] 자바 알고리즘 문제풀이 #10-06 6.최대점수 구하기(냅색 알고리즘)

문제

설명

이번 정보올림피아드대회에서 좋은 성적을 내기 위하여 현수는 선생님이 주신 N개의 문제를 풀려고 합니다.

각 문제는 그것을 풀었을 때 얻는 점수와 푸는데 걸리는 시간이 주어지게 됩니다.

제한시간 M안에 N개의 문제 중 최대점수를 얻을 수 있도록 해야 합니다.

(해당문제는 해당시간이 걸리면 푸는 걸로 간주한다, 한 유형당 한개만 풀 수 있습니다.)

 

입력

첫 번째 줄에 문제의 개수N(1<=N<=50)과 제한 시간 M(10<=M<=300)이 주어집니다.

두 번째 줄부터 N줄에 걸쳐 문제를 풀었을 때의 점수와 푸는데 걸리는 시간이 주어집니다.

 

출력

첫 번째 줄에 제한 시간안에 얻을 수 있는 최대 점수를 출력합니다.

 

예시 입력 1 

5 20
10 5
25 12
15 8
6 3
7 4

 

예시 출력 1

41

 

 

 

내 풀이
import java.util.*;

class Question{
    public int s, t;
    public Question(int s, int t){
        this.s = s;
        this.t = t;
    }
}
public class Main10_6 {
    static int[] dy;
    static int n, m;
    public int Solution(Question[] arr){
        Arrays.fill(dy, Integer.MIN_VALUE);
        dy[0] = 0;
        for (int i = 0; i < n; i++) { //문제의 개수
            for (int j = arr[i].t; j <= m; j++) {
                dy[j] = Math.max(dy[j], dy[j-arr[i].t]+arr[i].s);
            }
        }
        return dy[m];
    }

    public static void main(String[] args) {
        Main10_6 T = new Main10_6();
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        dy = new int[m+1];
        Question[] arr = new Question[n];
        for (int i = 0; i < n; i++) {
            int s = sc.nextInt();
            int t = sc.nextInt();
            arr[i] = new Question(s, t);
        }
        System.out.println(T.Solution(arr));
    }
}

동전 교환 문제는 동전을 무한대로 사용할 수 있었고,

위의 문제는 한 문제는 한 번씩만 사용할 수 있다는 점이 큰 차이점이다.

 

 

위의 빨간 글씨처럼 같은 문제를 여러 번 풀게되는 문제가 발생함.......!

입력 케이스에 대해 정답이 나와서 잠시나마 기뻤던ㅎㅎㅎㅎ

 

 

 

선생님 풀이
import java.util.*;

public class Main10_6 {
    public static void main(String[] args) {
        Main10_6 T = new Main10_6();
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] dy = new int[m+1];
        for (int i = 0; i < n; i++) {
            int ps = sc.nextInt();
            int pt = sc.nextInt();
            for (int j = m; j >=pt ; j--) {
                dy[j] = Math.max(dy[j], dy[j-pt]+ps);
            }
        }
        System.out.println(dy[m]);
    }
}

매번 느끼는 것 : 코드가 생각보다 짧고 간단해서 킹받음

핵심은 문제의 수가 유한하다면 거꾸로 도는 것이다.

오늘도 이렇게 이마를 탁 무릎을 탁 치고 간다....

 

 

 

결과