yha97 2023. 5. 4. 20:48

날짜 : 2023. 05. 04

사용 언어 : python

 

문제

 

 

코드

import sys
from itertools import combinations

n, m = map(int, sys.stdin.readline().split())
graph = list()
house = list()  # 집의 좌표
chicken = list()  # 치킨집 좌표

for _ in range(n):
    graph.append(list(map(int, sys.stdin.readline().split())))
for i in range(n): # 최대 2500
    for j in range(n):
        if graph[i][j] == 1:
            house.append([i, j])
        elif graph[i][j] == 2:
            chicken.append([i, j])

res = int(1e9)  # 도시의 치킨거리
for pick in combinations(chicken, m):  # 모든 치킨집 중에서 m개 뽑은 케이스 -> 최대 13C5 * 
    temp = 0
    for h in house:
        d = 10000  # 하나의 가구의 치킨거리
        for p in pick:
            d = min(d, abs(h[0]-p[0]) + abs(h[1]-p[1]))
        temp += d
    res = min(res, temp)
print(res)

 

 

풀이

- 치킨집, 가정집의 좌표를 각 리스트에 저장

- combinations를 활용해 전체 치킨집 중에서 m 개를 추출 -> pick

- 하나의 가정집을 토대로 pick한 치킨집에 대한 최소 치킨거리를 구한다.(하나의 가구 대한 치킨거리)

- 이를 temp 에 더한 후 모든 가정집에 대한 치킨거리 총합이 구해졌다면 이 값을 토대로 도시의 치킨거리의 최소값을 최신화한다.

 

 

알게된 점

- 시간복잡도를 고려해서 BFS로 구해볼까 했는데 너무 복잡해져서 다른사람의 풀이를 참고했고, combination으로 풀이하는 것을 알게 되었다.

- combination으로 m개를 뽑은 케이스를 만들면 이 케이스를 토대로 도시의 치킨거리를 구할 수 있다.

- 그리고 이 치킨거리를 모든 경우의수를 비교하면서 최소값으로 갱신하는 원리였다.

- 풀이 이후 시간복잡도를 구해보았는데 각각 2 ≤ N ≤ 50, 1 ≤ M ≤ 13 이었기 때문에 이중 for문에서는 50*50 = 2500, 3중 for문에선 O(13C6*2N*13) < 100,000,000 이었다. 그래서 combination을 활용한 브루트포스가 가능했던 것 같다.

 

 

 

참고 사이트

- https://codesyun.tistory.com/185

 

[BOJ / 백준] 15686번 치킨 배달 파이썬(Python) 문제 풀이

문제 문제 링크 : https://www.acmicpc.net/problem/15686 15686번: 치킨 배달 크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은

codesyun.tistory.com