큰수의 법칙 (그리디 알고리즘)

큰수의 법칙 (그리디 알고리즘)

[문제1] 큰 수의 법칙#

[문제] 큰 수의 법칙 : 문제 설명#

출제자는 큰 수의 법칙을 본인만의 방식으로 다르게 사용하고 있다. 이 큰 수의 법칙은 다양한 수로 이루어진 배열이 있을 때 주어진 수들을 M번 더하여 가장 큰수를 만드는 법칙이다. 단 배열의 특정한 인덱스(번호)에 해당하는 수가 연속해서 K번을 초과하여 더해질 수 없는 것이 이 법칙의 특징이다.

예를 들어 순서대로 2, 4, 5, 4, 6으로 이루어진 배열이 있을 때 M이 8이고, K가 3이라고 가정하자. 이 경우 특정한 인덱스의 수가 연속해서 세 번까지만 더해질 수 있으므로 큰 수의 법칙에 따른 결과는 6+6+6+5+6+6+6+5인 46이 된다.

배열의 크기 N, 숫자가 더해지는 횟수 M, 그리고 K가 주어질 때 출제자의 큰 수의 법칙에 따른 결과를 출력하시오

[문제] 조건#

조건 시간 1초, 메모리 120mb

입력조건 첫째 줄에 N(2 <= N <= 1,000), M(1 <= M <= 10,000), K(1 <= K <= 10,000)의 자연수가 주어지며, 각 자연수는 공백으로 구분한다. 둘째 줄에 N개의 자연수가 주어진다. 각 자연수는 공백으로 구분한다. 단, 각각의 자연수는 1 이상 10,000 이하의 수로 주어진다. 입력으로 주어지는 K는 항상 M보다 작거나 같다

출력조건 첫째 줄에 큰 수 의 법칙에 따라 더해진 답을 출력한다

입력예시 5 8 3 2 4 5 4 6

출력예시 46

아이디어#

최초 while 안에 k번의 반복문을 두어 큰수를 반복시키려고 했다만 문제 조건의 시간과 메모리의 조건이 있어 최대 입력값인 1000, 10000, 10000 이라면 열심히 풀고도 오답이 나올것이다.

n m k 5 7 2 2 1 5 4 3

{5, 5, 4, 5, 5, 4, 5}

코딩문제인줄 알았으나 수열문제 였다. 일단 5의 갯수를 세어 count * 5로 반복문 없이 계산을 하려한다.

첫번째로 반복되는 수열중 5의 갯수를 구하는 법이다. 반복되는 5, 5, 4는 (k+1) 3이며 전체의 총 개수에서 몇번 사용할 수 있는지 생각해 보면 m // (k+1) 몫은 2가 나온다. 여기에 k를 다시 곱해준다 (m // (+1) 2)*k 여기까지 계산하면 반복되는 수열중의 제일 큰 수를 계산한다.

하지만 수열에 포함되지 않은 5의 갯수를 더해줘야한다. 딱 나눠떨어지면 0, 나머지가 있다면 나머지 만큼의 5를 더해 줘야한다. 여기에 자주 쓰이는 % 연산자가 있다

m % (k+1) 으로 1이나온다. 나머지의 갯수를 계산하는 식 m % (k+1)

count = (m // (+1) 2)*k count += m % (k+1)

이렇게 하면 {(5), (5), 4, (5), (5), 4, (5)} 5의 개수를 얻었고 이제 4의 개수를 얻어보자 아까 구했던 수열이 반복되는 (m // (k+1)) 만큼 4를 곱해준다

count2 = (m // (k+1)) 나머지는 2번째 수가 나오지 못하여, 몫으로 안떨어지고 나머지가 된것이기 때문에 2번째 큰수는 나머지 추가로 더해줄게 없다

result = (count첫번째큰수)+(count2두번째큰수)

law_of_large_number.py#

n, m, k = map(int, input().split()) 
l = list(map(int, input().split()));
l.sort();

first = l[n-1] 
second = l[n-2]

count = (m // (k+1))*k 
count += m % (k+1)

count2 = (m // (k+1)) #m-count

result = (count*first) + (count2*second)

print(result)
     

LawOfLargeNumber.java#

package ex.Algorithm.greedy;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

public class LawofLargeNumber {
	
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		int result = 0;
		
		String str1 = sc.nextLine();
		String str2 = sc.nextLine();
		
		int n = Integer.parseInt(str1.split(" ")[0]);
		int m = Integer.parseInt(str1.split(" ")[1]);
		int k = Integer.parseInt(str1.split(" ")[2]);
		String list[] = str2.split(" ");
		Arrays.sort(list);
		
		int first = Integer.parseInt(list[n-1]);
		int second = Integer.parseInt(list[n-2]);
		
		//System.out.println("n"+n);
		//System.out.println("m"+m);
		//System.out.println("k"+k);
		//System.out.println("first"+first);
		//System.out.println("second"+second);
		
		//5 5 4 5 5 4 5
		
		int count = (m/(k+1))*k;
		count += m%(k+1);
		int count2 = m-count; 
		
		//System.out.println(count);
		
		result = (count*first) + (count2*second);
				
		System.out.println(result);
	}
}

이 자료는 나동빈님의 이코테 저서를 보고 정리한 자료입니다.