문제 링크

문제 요약

두 명의 플레이어 Vilius와 Adomas가 가위바위보 게임을 합니다. 각 플레이어는 가위, 바위, 보를 몇 번 냈는지 총 횟수는 알지만, 어떤 순서로 냈는지는 기억하지 못합니다. 게임의 점수 체계는 다음과 같습니다: Vilius가 이기면 +1점, Vilius가 지면 -1점, 비기면 0점입니다. 주어진 가위, 바위, 보 횟수를 바탕으로 Vilius가 얻을 수 있는 최대 점수와 최소 점수를 계산해야 합니다.

풀이

이 문제는 주어진 가위, 바위, 보의 총 횟수만 중요하고, 어떤 순서로 냈는지는 중요하지 않다는 점을 이용한 그리디(Greedy) 문제입니다. Vilius의 점수를 최대로 만들거나 최소로 만드는 두 가지 시나리오를 각각 고려하여 풀이할 수 있습니다.

Vilius의 점수를 최대로 만드는 경우: Vilius의 점수를 최대로 만들기 위해서는 Vilius가 이기는 경우(+1점)를 최대한 많이 발생시켜야 합니다. 그 다음으로는 점수에 영향을 주지 않는 비기는 경우(0점)를 처리하고, 마지막으로 점수를 잃는 지는 경우(-1점)를 최소화해야 합니다.

Vilius의 점수를 최소로 만드는 경우: Vilius의 점수를 최소로 만들기 위해서는 Vilius가 지는 경우(-1점)를 최대한 많이 발생시켜야 합니다. 그 다음으로는 점수에 영향을 주지 않는 비기는 경우(0점)를 처리하고, 마지막으로 점수를 얻는 이기는 경우(+1점)를 최소화해야 합니다.

정답 코드

def win(a, b):
  # 최대한 이길 수 있게 하기
  ret = 0
  for i in range(3):
    k = min(a[i], b[(i + 2) % 3]) 
    a[i] -= k
    b[(i + 2) % 3] -= k
    ret += k
  return ret
 
def tie(a, b):
  # 최대한 비기게 하기
  for i in range(3):
    k = min(a[i], b[i]) 
    a[i] -= k
    b[i] -= k
 
def lose(a, b):
  # 최대한 지도록 하기
  ret = 0
  for i in range(3):
    k = min(a[i], b[(i + 1) % 3]) 
    a[i] -= k
    b[(i + 1) % 3] -= k
    ret -= k
  return ret
 
def greedy_win(a, b):
  # Vilius가 이기는 경우를 최대로, 지는 경우를 최소로
  ret = 0
 
  ret += win(a, b) # Vilius가 이김
  tie(a, b) # 비김 (점수 영향 없음)
  ret += lose(a, b) # Vilius가 짐
 
  return ret
 
def greedy_lose(a, b):
  # Vilius가 지는 경우를 최대로, 이기는 경우를 최소로
  ret = 0
  ret += lose(a, b) # Vilius가 짐
  tie(a, b) # 비김 (점수 영향 없음)
  ret += win(a, b) # Vilius가 이김
  return ret
 
def solve():
  A = [*map(int, input().split())] # Vilius의 바위, 보, 가위 횟수 (0: 바위, 1: 보, 2: 가위)
  B = [*map(int, input().split())] # Adomas의 바위, 보, 가위 횟수
 
  # 최대 점수 계산 (A, B 리스트는 함수 내에서 변경되므로 복사본 전달)
  max_score = greedy_win(A[::], B[::])
  # 최소 점수 계산 (A, B 리스트는 함수 내에서 변경되므로 복사본 전달)
  min_score = greedy_lose(A[::], B[::])
 
  print(max_score)
  print(min_score)
 
if __name__ == "__main__":
  tc = 1
  for t in range(1, tc+1):
    ret = solve()
 

연관 페이지

참고 문헌 / 사이트