codingtest

거스름돈 계산하기 2

2024-09-26
2분 분량
JAVA프로그래머스

문제 설명

거스름돈 계산하기 2

정답률 34% · 제출 112회 · 예상 소요 시간 60분


곰돌이는 코드트리 마트에서 현재 일 하고 있습니다. 코드트리 마트에는 현재 N 가지의 동전들을 가지고 있고, 각 동전은 Ai​ 개를 가지고 있습니다.

곰돌이가 동전을 최소로 사용하여 거스름돈을 돌려주는 방법을 구하는 프로그램을 작성하세요.

입력 형식

첫번째 줄에 동전의 가지 수 N 과 돌려줘야 하는 거스름돈의 액수 S 가 공백을 사이에 두고 주어집니다.

두번째 줄부터 N 개의 줄에 걸쳐 각 동전의 가치 Vi​ 와, 가지고 있는 동전의 개수 Ai​ 가 공백을 사이에 두고 주어집니다.

단, 각 동전의 가치는 모두 다릅니다.

  • 1 ≤ N ≤ 1,000
  • 1 ≤ S ≤ 5,000
  • 1 ≤ Vi​ ≤ 2,000
  • 1 ≤ Ai​ ≤ 20

출력 형식

첫번째 줄에 곰돌이가 가장 적게 사용한 동전의 개수를 출력하세요. 만약 해당 거스름돈을 만들 수 없다면, -1을 출력하세요.

입출력 예제

예제1

입력:

5 21 1 1 2 3 3 4 4 5 5 2

출력:

5

예제2

입력:

2 20 3 2 9 3

출력:

1

문제 풀이 시간 : 1시간

문제 풀이 :

처음엔 그냥 되게 간단한 dp 문제인줄 알았는데

막상 풀려고 하니 dp를 어떤 식으로 코드를 짜야하는지 헷갈렸다.

초기 코드를 가져오고 싶은데

코드트리는 이미 지난 시험의 코드는 다시 볼 수 없는 것 같다.

그래서 기존 코드는 가져올 수 없지만

그냥 너무 생각을 깊게 했던게 독이 됐던 것 같다.

그래서 코드가 너무 더러웠고 복잡했다.

그래서 며칠 뒤에 다시 새로운 마음으로 문제를 봤더니 아주 간단한 문제라는 것을 알 수 있었다.

최종 코드

java
import java.util.*;
import java.io.*;

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 S = Integer.parseInt(st.nextToken());

        int[] dp = new int[S+1]; //최소 거스름돈 수를 저장하는 dp 배열

        for(int i=1;i<=S;i++){ //0원일떄를 제외하고 모두 무한으로 설정
            dp[i] = Integer.MAX_VALUE;
        }

        for(int i=0;i<N;i++){
            st = new StringTokenizer(br.readLine());
            int price = Integer.parseInt(st.nextToken()); //동전의 가격
            int count = Integer.parseInt(st.nextToken()); //동전을 가지고 있는 개수

            for(int j=0;j<=S;j++){ //0원부터 S원까지 반복
                if(dp[j]!=Integer.MAX_VALUE){ //현재 가격의 동전 개수가 무한이 아니라면
                    for(int k=1;k<=count;k++){ //동전의 개수만큼 반복
                        int idx = j+k*price; //다음 가격
                        if(idx>S){ //얻고자하는 가격을 넘으면 종료
                            break;
                        }
                        dp[idx] = Math.min(dp[idx],dp[j]+k); //원래 개수와 새로운 개수를 비교해서 최소값 저장
                    }
                }
            }
        }

        if(dp[S]==Integer.MAX_VALUE){ //해당 가격의 동전 개수가 무한이면 구할 수 없는 것
            System.out.println(-1);
        }
        else{ //구해져 있다면 출력
            System.out.println(dp[S]);
        }
    }
}

함께 읽으면 좋은 글

코딩 테스트2026-08-23

택배상자

order 배열은 택배 기사님이 원하는 상자 적재 순서다 기존 컨테이너 벨트는 1번부터 순서대로만 꺼낼 수 있다 보조 벨트는 스택처럼 마지막에 넣은 것부터 꺼낼 수 있다 원하는 순서대로 최대한 실을 수 있는 상자 개수를 구하는 문제다 처음에는 기존 벨트를 실제 리스트로 만들어…

코딩 테스트2026-08-23

롤케이크 자르기

topping 배열은 롤케이크에 일렬로 올라간 토핑 번호다 한 지점을 잘라 두 조각으로 나눴을 때, 양쪽 토핑 종류 수가 같아야 공평하게 나눈 것이다 공평하게 자를 수 있는 방법의 수를 구하는 문제다 처음에는 자르는 위치마다 왼쪽과 오른쪽 배열을 나눠서 각각 서로 다른 토핑…

코딩 테스트2026-08-23

할인 행사

want, number 배열로 정현이가 원하는 제품과 수량을 표현한다 discount 배열은 XYZ 마트가 매일 할인하는 제품 목록이다 연속된 10일 동안 할인 제품 종류와 수량이 want, number와 정확히 일치해야 회원가입할 수 있다 그런 시작일이 총 몇 번 있는지…

코딩 테스트2026-08-23

숫자 변환하기

자연수 x를 y로 바꾸는 데 x+n, x2, x3 세 가지 연산을 쓸 수 있다 x를 y로 바꾸는 최소 연산 횟수를 구하는 문제다 만들 수 없으면 -1을 반환한다 처음에는 x에서 시작해서 세 가지 연산을 재귀적으로 다 시도해보고 y에 도달하는 경로 중 가장 짧은 걸 고르면…