본문 바로가기
Algorithm/Python

[백준 2470번] 두 용액

by _sweep 2022. 3. 2.

문제 링크 >> https://www.acmicpc.net/problem/2470

 

 

📋 문제

KOI 부설 과학연구소에서는 많은 종류의 산성 용액과 알칼리성 용액을 보유하고 있다.

각 용액에는 그 용액의 특성을 나타내는 하나의 정수가 주어져있다.  

산성 용액의 특성 값은 1부터 1,000,000,000까지의 양의 정수로 나타내고, 알칼리성 용액의 특성 값은 -1부터 -1,000,000,000까지의 음의 정수로 나타낸다.

 

같은 양의 두 용액을 혼합한 용액의 특성값은 혼합에 사용된 각 용액의 특성 값의 합으로 정의한다.

이 연구소에서는 같은 양의 두 용액을 혼합하여 특성값이 0에 가장 가까운 용액을 만들려고 한다. 

 

예를 들어, 주어진 용액들의 특성값이특성 값이 [-2, 4, -99, -1, 98]인 경우에는 특성 값이 -99인 용액과 특성 값이 98인 용액을 혼합하면 특성 값이 -1인 용액을 만들 수 있고, 이 용액이 특성 값이 0에 가장 가까운 용액이다.

참고로, 두 종류의 알칼리성 용액만으로나 혹은 두 종류의 산성 용액만으로 특성값이 0에 가장 가까운 혼합 용액을 만드는 경우도 존재할 수 있다.

 

산성 용액과 알칼리성 용액의 특성 값이 주어졌을 때, 이 중 두 개의 서로 다른 용액을 혼합하여 특성 값이 0에 가장 가까운 용액을 만들어내는 두 용액을 찾는 프로그램을 작성하시오.

 

 

👉 입력

첫째 줄에는 전체 용액의 수 N이 입력된다.

N은 2 이상 100,000 이하이다.

둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다.

이 수들은 모두 -1,000,000,000 이상 1,000,000,000 이하이다.

N개의 용액들의 특성값은 모두 다르고, 산성 용액만으로나 알칼리성 용액만으로 입력이 주어지는 경우도 있을 수 있다.

 

 

👈출력

첫째 줄에 특성값이 0에 가장 가까운 용액을 만들어내는 두 용액의 특성 값을 출력한다.

출력해야 하는 두 용액은 특성값의 오름차순으로 출력한다.

특성 값이 0에 가장 가까운 용액을 만들어내는 경우가 두 개 이상일 경우에는 그중 아무것이나 하나를 출력한다.

 

 

📝 풀이

❌ 첫 번째 풀이

import sys
input = sys.stdin.readline

n = int(input())
arr = sorted(list(map(int, input().split())))

if arr[0] < 0 and arr[-1] < 0:
  # 용액이 모두 알칼리성일 경우
  print(arr[-1], arr[-2])
elif arr[0] > 0 and arr[-1] > 0:
  # 용액이 모두 산성일 경우
  print(arr[0], arr[1])
else:
  start, end = 0, n-1
  minNum = 1000000001
  result = [(0, 0)]
  
  while start < end:
    num = arr[start] + arr[end]
    
    if num < minNum:
      minNum = num
      result.pop()
      result.append((arr[start], arr[end]))
    
    start += 1
    end -= 1
  print(*result[0], sep=' ')

 

용액이 모두 산성일 경우, 용액이 모두 알칼리성일 경우, 산성과 알칼리성이 섞여있을 경우로 케이스를 나누었다.

먼저 arr에 용액의 특성값을 담고 이를 정렬한다.

arr 인덱싱에 사용할 포인터인 start와 end에 각각 0, n-1의 값을 담는다.

그리고 while문 안에서 arr[start] + arr[end]의 값을 담은 num을 비교해가며 최솟값을 찾는다.

num이 최소값일 경우 result에 담고 start와 end의 값을 바꾸며 범위를 좁혀나간다.

 

이 풀이는 당연하게도... 틀렸다.

일단 합이 음수가 되는 경우 최솟값을 잘못 찾고 있기 때문이다.

예를 들어 입력이 [-99, -98, -3, -2, 98]과 같은 경우 정답은 -99와 98이지만 아래 사진처럼 계산해 -98과 -2가 출력된다.

 

 

따라서 비교할 때는 절댓값을 사용해야 하고 이 값에 따라 포인터를 움직이는 것도 다르게 설정해야 한다.

 

✔️ 두 번째 풀이

import sys
input = sys.stdin.readline

n = int(input())
arr = sorted(list(map(int, input().split())))

start, end = 0, n-1
minNum = 9223372036854775807
result = []
  
while start < end:
  num = arr[start] + arr[end]
    
  if abs(num) < minNum:
    minNum = abs(num)
    result = [arr[start], arr[end]]
    
  if num < 0:
    start += 1
  else:
    end -= 1
      
print(*result, sep=' ')

 

두 번째 풀이에서는 경우를 나누지 않고 바로 계산했다.

이 과정에서 최소값을 저장할 변수인 minNum의 값을 최대 정수인 9223372036854775807로 설정했다.

Python3에서는 사라진 문법이지만 기존 Python2의 sys.maxint의 값이 9223372036854775807과 같다고 한다.

 

arr에 정렬된 특성값들을 담고 arr 인덱싱을 할 start와 end를 0, n-1로 선언하는 것은 첫 번째 풀이와 동일하다.

while문을 돌며 num에 arr[start] + arr[end]의 값을 담는다.

그리고 num의 절댓값과 minNum을 비교한다.

만약 최소값이 갱신된다면 minNum에는 num의 절댓값을 넣어주고 result에 arr[start]와 arr[end]의 값을 저장해둔다.

 

그리고 num의 값이 0보다 큰지 작은지 비교한다.

만약 num이 0보다 작다면(음수라면) start를 움직이고 num이 0보다 크다면 end를 움직인다.

 

while문이 끝나면 result의 값을 출력한다.

 

 

 

참고로 백준 2467번 용액 문제도 이 문제와 동일한 것 같은데 왜 나누어져 있는지 모르겠다.

아무튼 위 코드로 2467번 용액 문제와 2470번 두 용액 문제 모두 통과할 수 있었다.

 

 

🔍 참조

python 최대 정수 https://www.delftstack.com/ko/howto/python/python-max-int/

 

 

 

 

 

'Algorithm > Python' 카테고리의 다른 글

[프로그래머스] 더 맵게  (0) 2022.03.04
[백준 7453번] 합이 0인 네 정수  (0) 2022.03.04
[프로그래머스] 소수 찾기  (0) 2022.03.02
[백준 17609번] 회문  (0) 2022.03.01
[백준 1806번] 부분합  (0) 2022.03.01

댓글