[이코테] 실전문제: 큰 수의 법칙
큰 수의 법칙
문제
큰 수의 법칙은 다양한 수로 이루어진 배열이 있을 때 주어진 수들을 M번 더하여 가장 큰수를 만드는 법칙이다. 단 배열의 특정한 인덱스(번호)에 해당하는 수가 연속해서 K번을 초과하여 더해질 수 없는 것이 이 법칙의 특징이다.
예를 들어 순서대로 2, 4, 5, 4, 6으로 이루어진 배열이 있을 때 M이 8이고, K가 3이라고 가정하자. 이 경우 특정한 인덱스의 수가 연속해서 세 번까지만 더해질 수 있으므로 큰 수의 법칙에 따른 결과는 6+6+6+5+6+6+6+5인 46이 된다.
입력조건
-
첫째 줄에 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
나의 코드
첫 번째 시도.
N,M,K=map(int,input().split()) num=list(map(int,input().split())) num=sorted(num) print((M//K)*(K*num[-1])+(M%K)*(num[-2]))
🌝 Thinking
반례가 존재함(앞에서 부터 큰 수를 꽉꽉채워가면서 나오는 나머지임으로 정확하지가 않음.)
떠올렸던 원리를 그대로 따라가서 구현했어야했음. 그래서 그리디?
두 번째 시도
N,M,K=map(int,input().split()) num=list(map(int,input().split())) num=sorted(num) first = num[N-1] second = num[N-2] sum=0 while True: for i in range(K): sum+=first M-=1 sum+=second M-=1 if M==0: break print(sum)
🌝 Thinking
정답임을 확신하고 답안 알고리즘과 대조를함. 두번 째 시도 또한 문제가 있었음.
M==0이면 루프를 빠져나오는 조건을 맨 마지막 한번 만 주었기에 M=1일때 오답이 나옴.
답안 예시1
N,M,K=map(int,input().split())
num=list(map(int,input().split()))
num=sorted(num)
first = num[N-1]
second = num[N-2]
sum=0
while True:
for i in range(K):
if M==0:
break
sum+=first
M-=1
if M==0:
break
sum+=second
M-=1
print(sum)
아까웠군,,,
답안예시2
시간을 단축 시키는 좋은 알고리즘.
N,M,K = map(int,input().split())
data=list(map(int,input().split()))
data.sort()
first = data[N-1]
second = data[N-2]
count = (M//(K+1))*K
count+= M%(K+1)
result = 0
result += count * first
result += (M-count)*second
print(result)
💡 깨달은 점.
-
루프를 빠져나올때 항상 꼼꼼히 생각하는 연습을 해야겠다.
-
연산횟수가 1억이 넘어간다면 …? 내가 떠 올렸던 첫번째 발상을 조금더 꼼꼼이 다듬었다면 충분히 좋은 알고리즘을 만들 수 있었다. 엄밀하게 코드를 짜는 연습을 더 해야겠다.
출처
이것이 코딩 테스트다 - 나동빈 저
댓글남기기