Algorithm/Simulation

[Python] 치킨배달

코딩쪼앙 2023. 1. 26. 18:38

문제

  • 크기가 N x N인 도시가 있습니다.
  • 도시는 1 x 1 크기의 칸으로 나누어져 있습니다.
  • 도시의 각 칸은 빈칸, 치킨집, 집 중 하나입니다.
  • 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸, 왼쪽에서부터 c번째 칸을 의미합니다.
  • r과 c는 1부터 시작합니다.
  • 이 도시에 사는 사람들은 치킨을 매우 좋아합니다. 따라서 사람들은 "치킨 거리"라는 말을 주로 사용합니다.
  • 치킨 거리는 집과 가장 가까운 치킨집 사이의 거리입니다.
  • 즉, 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있습니다.
  • 도시의 치킨 거리는 모든 집의 치킨 거리의 합입니다.
  • 임의의 두 칸 (r1, c1)과 (r2, c2) 사이의 거리는 |r1-r2| + |c1-c2| 로 구합니다.
  • 0은 빈 칸, 1은 집, 2는 치킨집입니다.
  • (2, 1)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |2-1| + |1-2| = 2, (5, 5)에 있는 치킨집과의 거리는 |2-5| + |1-5| = 7입니다. 따라서, (2, 1)에 있는 집의 치킨 거리는 2입니다.
  • (5, 4)에 있는 집과 (1, 2)에 있는 치킨집과의 거리는 |5-1| + |4-2| = 6, (5, 5)에 있는 치킨집과의 거리는 |5-5| + |4-5| = 1입니다. 따라서, (5, 4)에 있는 집의 치킨 거리는 1입니다.
  • 이 도시에 있는 치킨집은 모두 같은 프랜차이즈입니다.
  • 프랜차이즈 본사에서는 수익을 증가시키기 위해 일부 치킨집을 폐업시키려고 합니다.
  • 오랜 연구 끝에 이 도시에서 가장 수익을 많이 낼 수 있는 치킨집의 개수는 최대 M개라는 사실을 알아냈습니다.
  • 도시에 있는 치킨집 중에서 최대 M개를 고르고, 나머지 치킨집은 모두 폐업시켜야 합니다.
  • 어떻게 고르면, 도시의 치킨 거리가 가장 작게 될지 구하는 프로그램을 작성하세요.

입력

  • 첫째 줄에 N(2 <= N <= 50)과 M(1 <= M <= 13)이 주어집니다.
  • 둘째 줄부터 N개의 줄에는 도시의 정보가 주어집니다.
  • 도시의 정보는 0, 1, 2로 이루어져 있고, 0은 빈칸, 1은 집, 2는 치킨집을 의미합니다.
  • 집의 개수는 2N개를 넘지 않으며, 적어도 1개는 존재합니다.
  • 치킨집의 개수는 M보다 크거나 같고, 13보다 작거나 같습니다.

출력

  • 첫째 줄에 폐업시키지 않을 치킨집을 최대 M개를 골랐을 때, 도시의 치킨 거리의 최솟값을 출력합니다.

입력 예시

5 3
0 0 1 0 0
0 0 2 0 1
0 1 2 0 0
0 0 1 0 0
0 0 0 0 2

출력 예시

5

문제 풀이

  • m개의 치킨 집을 뽑기 위해 combination사용
  • 조합 중 뽑힌 치킨 집들과 각 집의 최소 거리 구하여 최소 치킨 거리 구하기 (getsum 함수로 구현)
  • 최소 치킨 거리가 나오는 조합을 찾아 그 값 출력

코드

from itertools import combinations
n, m = map(int,input().split())
chicken, house = [], []

# 치킨집과 집 좌표 저장
for r in range(n):
    data = list(map(int,input().split()))
    for c in range(n):
        if data[c] == 1:
            house.append((r, c))
        elif data[c] == 2:
            chicken.append((r,c))

# 모든 치킨집에서 m개 뽑는 조합 계산
candidates = list(combinations(chicken,m))
# 치킨거리 합 구하는 함수
def getsum(candidates):
    result = 0
    for hy, hx in house:
        temp = 1e9
        for cy, cx in candidates:
            temp = min(temp,abs(hy - cy) + abs(hx - cx))
        result += temp
    return result
result = 1e9

# 최소 치킨거리 구하기
for candidate in candidates:
    result = min(result,getsum(candidate))
print(result)