Greedy-큰 수의 법칙
문제
- 책, ‘이것이 취업을 위한 코딩 테스트다’ / ch3 Greedy / 예제 3-2 (p.92)
N : 숫자 종류의 갯수
M : 더하는 횟수
K : 연속해서 등장할 수 있는 최대 횟수
=> 해당 조건 하에 주어진 수들들을 M번 더하여 가장 큰 수를 만드시오.
Step 1. 문제 접근
최종적으로 숫자들을 M번 더한 값이 가장 큰 값이 되려면, 후보 숫자들 중 최대한 큰 숫자들을 더해나가야한다
Step 2. 선택한 알고리즘
Greedy 알고리즘
-
- Greedy (탐욕법)
-
현재 상황(고려하는 turn)에서 당장 좋은 것만 고르는 방법 (이후는 고려하지 X)
Step 3. 선택 이유
이 문제는 가장 큰 수들을 가능한 횟수만큼 더하면 최적의 해가 나오는 문제이다(가능한 선에서 계속 큰 숫자만 선택한다.)
즉, 다른 숫자를 더하는 경우는 생각하지 않고 가능한 숫자중 가장 큰 숫자만 매 횟수마다 더한다(M번) .
=> 가장 큰 숫자를 계속 더해주면서 최대 연속횟수를 초과하지 않게끔만 두번째로 큰 숫자를 중간중간 넣어준다
Step 4. 구현 (코드)
-
해당 원리를 이용하여, 수학적 아이디어를 도출한다 : 반복되는 수열 파악
-
가장 큰 수와 두 번째로 크ㅡㄴ수가 더해질 때는 특정한 수열 형태로 일정하게 반복해서 더해짐
ex) {6, 6, 6, 5} , {6, 6, 6, 5}
-
반복되는 수열 길이 : K+1
; 연속해서 나오는 가장 큰 수의 횟수 (<-> 연속가능한 최대 등장 횟수) + 두번째 숫자 등장 횟수 (1회)
-
수열이 반복되는 횟수 : M / K+1
-
가장 큰 수가 등장하는 횟수 (수열에 포함) : (M / K+1 ) X K
-
수열을 완성시키지 못한 숫자들은 자동적으로 가장 큰 수 : m % (k+1) ;
-
import java.util.* ;
public class 가장큰수 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in) ;
int n = sc.nextInt() ; // 숫자 종류의 갯수
int m = sc.nextInt(); // 더하는 횟수
int k = sc.nextInt(); // 연속해서 등장할 수 있는 최대 횟수
// part 1. 숫자 종류 입력 받기
int[] arr = new int[n] ;
for (int i = 0; i < n ; i++) {
arr[i] = sc.nextInt();
}
// part 2. 더할 숫자 준비
/*
* 사용한 아이디어: 가장 큰 숫자를 계속 더해주면서 최대 연속횟수를 초과하지 않게끔만 두번째로 큰 숫자를 중간중간 넣어준다
*/
Arrays.sort(arr);
int first = arr[n-1] ;
int second = arr[n-2] ;
// part 3. 수학적 아이디어로 변환 - 해당 두 숫자의 반복되는 횟수 구하기
int cnt = (m / (k+1)) * k ; // 가장 큰 숫자가 반복되는 횟수
cnt += m % (k+1) ; // 수열을 완성시키지 못한 숫자들은 자동적으로 가장 큰 수 -> 가장 큰 수 등장 횟수에 포함
// part 4. 정답 구하기 - 횟수만큼 숫자 더하기
int result = 0 ;
result += cnt * first ; // 첫번째로 큰 숫자 * 등장 횟수
result += (m - cnt) * second ; // 두번째로 큰 숫자 * 등장 횟수 (최종 등장 횟수 - 첫번째 수수자 등장 횟수)
System.out.println(result) ;
}
}
댓글남기기