코딩 테스트/그리디

백준 5911 - 선물 (자바 - 그리디)

방구석 대학생 2023. 5. 23. 17:02

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

 

5911번: 선물

1, 2, 4번 친구의 선물을 구매하고, 3번 친구의 선물을 쿠폰을 써서 구매하면 된다. (4+2)+(2+0)+(4+1)+(6+3) = 22 이기 때문에, B원으로 모두 구매하고 배송보낼 수 있다. 또, 1번이나 4번 친구에게 쿠폰을

www.acmicpc.net

 

* 문제 요약

군대에 가기 전까지 자신과 놀아준 친구 N (1 <= N <= 1,000) 명에게 선물을 주려고 한다.

돈을 B (1 <= B <= 1,000,000,000) 원 가지고 있다.

i 번째 친구가 받고 싶어하는 선물의 가격은 P(i) 원 이고, 배송비는 S(i) 원이다.

즉, i 번째 친구에게 선물을 보내려면 돈이 P(i) + S(i) 원 필요하다.

물건 가격을 절반으로 할인 받을 수 있는 쿠폰을 하나 가지고 있다. 이 쿠폰을 i 번째 친구에게 사용한다면 (P(i) / 2) + S(i) 원만 있으면 선물을 보낼 수 있다.

선물을 최대 몇 명에게 보낼 수 있는지 구하는 프로그램을 작성하시오.

 

* 입력

첫째 줄에 N 과 B 가 주어진다.

둘째 줄부터 N 개 줄에는 P(i) 와 S(i) 가 주어진다. (0 <= P(i), S(i) <= 1,000,000,000)

 

* 출력

첫째 줄에 선물을 최대 몇 명에게 보낼 수 있는지 출력한다.

 

* 예시

 

* 해결 과정

매 반복마다 현재 반값 할인을 적용할 선물과 그렇지 않을 선물 각각의 총 비용을 배열에 저장한다.

그 다음 배열을 오름차순 정렬해주고, 비용이 적게드는 선물 부터 순서대로 현재 가진 돈 B 안에서 살 수 있는지 검증한다.

반복을 통해 각 선물들을 구매하다가 다음 선물을 살 비용이 부족해지면 지금까지 구매한 선물 갯수와 이전의 반복에서 다른 선물에 반값 할인을 적용시켜서 구매 가능했던 총 선물 갯수와 비교해서 더 큰값을 저장해주는 방식으로 최종적인 최대값을 찾았다.

 

* 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {
        new Main().solution();
    }

    private void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String[] input = br.readLine().split(" ");
        int count = Integer.parseInt(input[0]);
        int money = Integer.parseInt(input[1]);

        Friend[] friends = new Friend[count];
        for (int i = 0; i < count; i++) {
            input = br.readLine().split(" ");
            int price = Integer.parseInt(input[0]);
            int transportPrice = Integer.parseInt(input[1]);

            Friend friend = new Friend(price, transportPrice);
            friends[i] = friend;
        }

        int max = Integer.MIN_VALUE;
        for (int i = 0; i < count; i++) {
            int[] totalArray = new int[count];
            for (int j = 0; j < totalArray.length; j++) {
                if (i == j) {
                    totalArray[j] = (friends[j].price / 2) + friends[j].transportPrice;
                } else {
                    totalArray[j] = friends[j].price + friends[j].transportPrice;
                }
            }

            Arrays.sort(totalArray);
            long sum = 0;
            int success = 0;
            for (int j = 0; j < totalArray.length; j++) {

                sum += totalArray[j];
                if (sum > money) {
                    break;
                } else {
                    success++;
                }
            }
            max = Math.max(max, success);
        }

        bw.write(max + "\n");
        bw.flush();
        bw.close();
        br.close();
    }
}

class Friend {
    int price;
    int transportPrice;

    public Friend(int price, int transportPrice) {
        this.price = price;
        this.transportPrice = transportPrice;
    }
}

 

매 반복마다 반값 할인을 받는 선물을 다르게 적용해가며 기본 자금 B 안에서 선물을 얼마나 살 수 있는지 산출해냈고, 그 중에서 가장 많은 선물을 사는 경우를 구했다.

반값 할인을 받는 선물이 제 각각 달라지는 상황에 맞게끔 가지고 있는 자금 내부에서 구매할 수 있는 최적의 선물 갯수를 구하며, 그 중 가장 큰 값을 찾았으므로 그리디 알고리즘, 그리고 모든 선물들에 대해 한 번씩 반값 할인을 적용하여 선물을 얼마나 살 수 있는지 알아냈으므로 브루트포스 알고리즘에 해당된다.