오늘 문제도 그리디 알고리즘 유형의 문제입니다.
옛날 옛적에 수학이 항상 큰 골칫거리였던 나라가 있었다. 이 나라의 국왕 김지민은 다음과 같은 문제를 내고 큰 상금을 걸었다.
길이가 N인 정수 배열 A와 B가 있다. 다음과 같이 함수 S를 정의하자.
S = A[0] × B[0] + ... + A[N-1] × B[N-1]
S의 값을 가장 작게 만들기 위해 A의 수를 재배열하자. 단, B에 있는 수는 재배열하면 안 된다.
S의 최솟값을 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. 둘째 줄에는 A에 있는 N개의 수가 순서대로 주어지고, 셋째 줄에는 B에 있는 수가 순서대로 주어진다. N은 50보다 작거나 같은 자연수이고, A와 B의 각 원소는 100보다 작거나 같은 음이 아닌 정수이다.
출력
첫째 줄에 S의 최솟값을 출력한다.
예제 입력 1 복사
5
1 1 1 6 0
2 7 8 3 1
예제 출력 1 복사
18
예제 입력 2 복사
3
1 1 3
10 30 20
예제 출력 2 복사
80
예제 입력 3 복사
9
5 15 100 31 39 0 0 3 26
11 12 13 2 3 4 5 9 1
예제 출력 3 복사
528
힌트
예제 1의 경우 A를 {1, 1, 0, 1, 6}과 같이 재배열하면 된다.
길이가 N인 정수 배열 A와 B가 있습니다. 이 상황에서 함수 S는 다음과 같이 정의합니다.
S = A[0] × B[0] + ... + A[N-1] × B[N-1]
S의 값을 가장 작게 만들기 위해 A의 수를 재배열할 수 있습니다. 단, B에 있는 수는 재배열하면 안됩니다.
이 문제는 이러한 조건에서 S의 최솟값을 구하는 문제입니다.
A의 수를 재배열할 수 있지만 B에 있는 수는 재배열하면 안된다라… 이 문장을 기억하고 넘어가도록 하겠습니다.
그럼 입력, 출력, 제약 조건을 확인해보겠습니다.
이번 문제는 시간 복잡도에 대해 큰 고민은 안해도 될 것 같습니다. 그리고 예외 케이스도 없습니다. 이제, 조금더 자세하게 문제를 들여다 보겠습니다.
이 문제는 그리디 알고리즘의 대표적인 예입니다. 그리디 알고리즘은 매 순간 최적의 선택을 함으로써 문제를 해결하려는 접근법입니다.
S
를 최소화하기 위해서는 각 곱셈의 결과가 작아야 합니다.A
를 오름차순, B
를 내림차순으로 정렬한 뒤 계산해도 문제의 제약을 만족합니다.A
는 오름차순으로 정렬합니다.B
는 내림차순으로 정렬합니다.S
를 계산합니다.import sys
N = int(sys.stdin.readline().strip())
A = list(map(int,sys.stdin.readline().split()))
B = list(map(int,sys.stdin.readline().split()))
def sol(N, A, B):
A.sort()
B.sort(reverse=True)
result = 0
for i in range(N):
result += A[i] * B[i]
return result
print(sol(N=N, A=A, B=B))
코드 설명:
N
: 정수 배열의 크기A
, B
: 두 배열로 입력받습니다.A.sort()
: 오름차순 정렬로 작은 값을 앞에 배치.B.sort(reverse=True)
: 내림차순 정렬로 큰 값을 앞에 배치.A[i]
와 B[i]
를 곱하여 누적 합산합니다.시간 복잡도:
A.sort()
: B.sort(reverse=True)
: 결과:
전체 코드는 다음 링크에서 확인할 수 있습니다.
읽어주셔서 감사합니다!!
어제보다 발전된 나!