[구름톤 챌린지] Day 15 과일 구매 (Java)

2023. 9. 1. 20:14·Algorithms(CT)/Goorm
 

구름LEVEL

난이도별 다양한 문제를 해결함으로써 SW 역량을 향상시킬 수 있습니다.

level.goorm.io

전체 코드는 맨 아래에 있습니다!

 

 

문제 설명

마트에서 팔고 있는 과일은 N 종류가 한 개씩 있고, 각 과일의 가격은 P, 그리고 과일을 먹었을 때 그 과일의 포만감은 C이다.

이 마트에서는 과일을 조각 단위로 구매하는 것이 가능하다.

가격이 P인 과일을 조각 단위로 구매하고자 할 경우, 이 과일을 P개의 조각으로 자른 뒤 그중 원하는 몇 개의 조각만을 구매할 수 있다.

이때 모든 조각의 가격은 1, 먹었을 때 얻을 수 있는 포만감은 C/P로 동일합니다.

 

플레이어가 K의 돈을 가지고, 주어진 금액 이내에서 과일들의 포만감 합이 가장 크게 되도록 과일을 선택하려고 합니다.

플레이어가 최적의 방법에 따라 과일을 구매했을 때, 구매한 과일들의 최대 포만감 합을 구해보자.

 

 

//입력
6 13 // n:과일의 개수, k: 플레이어가 가진 돈
2 8 //각 과일의 가격, 과일을 먹었을 때의 포만감
7 35
1 5
3 12
10 30
1 7

//출력
63 //구매한 과일들의 최대 포만감 합

T I P

  • 과일은 조각 단위로 살 수 있다는 점에 유의해야 합니다.
  • 그 과일 가격보다 내가 가진 돈이 적더라도 조각단위로 살 수 있습니다.
  • 가진 돈으로 가장 큰 포만감을 얻어내기 위해서는 단위당 가장 큰 포만감을 주는 과일을 골라야 합니다.
  • 따라서 단위당 포만감이 가장 큰 과일부터 선택해 나가는 Greedy(탐욕법) 알고리즘을 사용합니다.

 

풀이 과정

1. 주어진 변수들을 모두 저장해 줍니다.

n: 과일 개수, k: 가진 돈,  마트에 있는 과일들은 ArrayList <int []> 형으로 가격과 포만감을 같이 저장해 줍니다.

String[] s = br.readLine().split(" ");
int n = Integer.parseInt(s[0]);//과일 개수
int k = Integer.parseInt(s[1]);//플레이어가 가진 돈

ArrayList<int[]> fruits = new ArrayList<>();//마트에 있는 과일
for(int i=0;i<n;i++){
    s = br.readLine().split(" ");
    fruits.add(new int[]{Integer.parseInt(s[0]),Integer.parseInt(s[1])});//과일가격, 포만감
}

 

2.  조각단위로 살 수 있기 때문에, 가장 큰 포만감을 얻기 위해서는 단위 가격당 포만감이 많은 순으로 사면됩니다.

과일들을 가격이 1일 때의 포만감을 기준으로 정렬을 해서, 그 순서대로 과일을 불러올 것입니다.

 

(과일 가격 1당 포만감 :(포만감) / (가격) -> 포만감은 항상 가격의 배수로 주어지기 때문에 double 형으로 고려 X)

//가격 1당 포만감이 많이 차는 순으로 과일 정렬
Collections.sort(fruits, (a,b)->b[1]/b[0] - a[1]/a[0]);

 

람다식으로 정렬 구현하는 방법

더보기

예를 들어, Arrays.sort(arr, (x, y) -> y-x);라고 주어졌을 때

내가 작성한 (x, y)를 매개변수로 하여  x(앞에 오는 숫자), y(뒤에 오는 숫자)입니다.

->  뒤의 값이 양수가 나오는지, 음수가 나오는지에 따라 정렬됩니다.

->뒤의 식을 계산한 값이 음수가 나오면 그대로 두고, 양수가 나오면 자리를 바꿔줍니다.

-> 뒤의 식이 지금 y-x이기 때문에 현재 x=7, y=3에서 y-x=-4이므로 자리를 바꾸지 않습니다.

 

뒤의 숫자로 넘어가서 

이때의 y-x는 4-3=1로 양수가 나오기 때문에 자리를 바꿔 [7, 4, 3, 6, 1]이 됩니다. 

...

 

 

이것을 반대로 생각해 본다면

람다식을 정렬에 직접 사용할 수 있게 됩니다.

 

Arrays.sort(arr, (x, y) -> x-y);

x-y가 양수일 때 배열에서 서로 자리를 바꾼다 -> x-y>0 -> x> y 일 때 서로 자리를 바꾼다는 말이 됩니다.

결과적으로는 x <=y가 성립하는 배열이 위와 같은 오름차순 배열로 정렬됩니다.

 

반대로도 마찬가지로

Arrays.sort(arr, (x, y) -> y-x);

y-x가 양수일 때 숫자가 서로 자리를 바꾼다 -> y-x>0 -> y> x 일 때 서로 자리를 바꾼다는 말로

위와 같은 내림차순 배열이 만들어집니다.

 

3. 단위 가격당 포만감이 큰 과일 순서대로 ->  가진 돈을 모두 쓸 때까지 얻을 수 있는 포만감을 구하면 됩니다.

반복문을 사용해서 과일을 하나씩 가져와 줍니다.

산 과일들의 포만감을 모두 더해 full에 저장한 뒤 출력해 줍니다.

long full=0;//포만감 -> K, P, C 모두 정수 범위가 크기 때문에 포만감을 Long형으로 구현해줘야 합니다.
for(int[] fruit: fruits){//for-each구문으로 fruits 리스트에서 값을 하나씩 가져와 fruit에 넣어줍니다.
    if(k==0) break;//돈을 모두 썼다면 반복문 종료.

    if(k>=fruit[0]){//만약 과일을 하나를 통째로 살 수 있다면 사기.
        k-=fruit[0];//(현재 가진 돈 = 현재 가진 돈 - 과일 가격)
        full+=fruit[1];//포만감 = 포만감 + 현재 과일의 포만감
        
    }else{//만약 과일을 통째로 살 수 없다면 -> 조각으로 사기
        full+=fruit[1]/fruit[0]*k; //(가격 1당 포만감) * (가지고 있는 가격:k)
        k=0;//사는 조각 갯수 ( 조각은 1원단위로 나눠져 있음.)
    }
}

System.out.println(full); //구매한 과일들의 최대 포만감 합

전체 코드

import java.io.*;
import java.util.*;
class Main {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] s = br.readLine().split(" ");
		int n = Integer.parseInt(s[0]);//과일 개수
		int k = Integer.parseInt(s[1]);//플레이어가 가진 돈
		
		ArrayList<int[]> fruits = new ArrayList<>();//마트에 있는 과일
		for(int i=0;i<n;i++){
			s = br.readLine().split(" ");
			fruits.add(new int[]{Integer.parseInt(s[0]),Integer.parseInt(s[1])});//과일가격,포만감
		}
		//가격 1당 포만감이 많이 차는 순으로 과일 정렬
		Collections.sort(fruits, (a,b)->b[1]/b[0] - a[1]/a[0]);
		
		long full=0;//포만감 -> K, P, C 모두 정수 범위가 크기 때문에 포만감을 Long형으로 구현해줘야 합니다.
		for(int[] fruit: fruits){//for-each구문으로 fruits 리스트에서 값을 하나씩 가져와 fruit에 넣어줍니다.
			if(k==0) break;//돈을 모두 썼다면 반복문 종료.
			
			if(k>=fruit[0]){//만약 과일을 하나를 통째로 살 수 있다면 사기.
				k-=fruit[0];//(현재 가진 돈 = 현재 가진 돈 - 과일 가격)
				full+=fruit[1];//포만감 = 포만감 + 현재 과일의 포만감
				
			}else{//만약 과일을 통째로 살 수 없다면 -> 조각으로 사기
				full+=fruit[1]/fruit[0]*k; //(가격 1당 포만감) * (가지고 있는 가격:k)
				k=0;//사는 조각 갯수 ( 조각은 1원단위로 나눠져 있음.)
			}
		}
		System.out.println(full); //구매한 과일들의 최대 포만감 합
	}
}

후기

구름톤 챌린지 덕분에 매일매일 문제 푸는 감을 잊지 않고 풀고 있습니다!

매일 올라오는 코드를 보면서 한 번 더 공부하게 되네요!! 

다들 5일 남았으니까 파이팅 해요!! 👊 😎

'Algorithms(CT) > Goorm' 카테고리의 다른 글

[구름톤 챌린지] Day 18 중첩 점 (Java)  (0) 2023.09.07
[구름톤 챌린지] Day12 발전기 (Java)  (0) 2023.08.29
[구름톤 챌린지] Day11 통증 (2)  (0) 2023.08.29
[구름톤 챌린지] Day8. 통증 (Java)  (0) 2023.08.23
[구름톤 챌린지] Day7 구름 찾기 깃발 (Java)  (0) 2023.08.23
'Algorithms(CT)/Goorm' 카테고리의 다른 글
  • [구름톤 챌린지] Day 18 중첩 점 (Java)
  • [구름톤 챌린지] Day12 발전기 (Java)
  • [구름톤 챌린지] Day11 통증 (2)
  • [구름톤 챌린지] Day8. 통증 (Java)
gwee_99
gwee_99
bE bETTER!
  • gwee_99
    얼렁이와 뚱땅이
    gwee_99
  • 전체
    오늘
    어제
    • ====Category====
      • Algorithms(CT)
        • Programmers
        • Baekjoon
        • Goorm
      • Web
        • Error 해결
      • BackEnd
        • Spring
        • JPA
      • FrontEnd
        • HTML.CSS
        • JavaScript
      • Language
        • Java
      • Cloud
      • CSTS
      • Books
        • IT 5분 잡학사전
      • 일상
  • 블로그 메뉴

    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    Til
    백준
    lv2
    DFS
    HTML
    BFS
    Greedy
    따라하며 배우는 html css
    프로그래머스
    존안님
    자바
    제대로 파는 자바스크립트
    Lv.1
    DP
    LV.2
    스택
    lv.4
    그리디
    코딩테스트
    구름톤 챌린지
    IT 잡학사전
    LV.3
    개발자북클럽
    java
    인프런
    BOJ
    IT 5분 잡학사전
    호텔 대실
    구름
    노마드코더
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gwee_99
[구름톤 챌린지] Day 15 과일 구매 (Java)
상단으로

티스토리툴바