전산/Algorithm

[Python][구현/BFS/조합] 치킨 배달 - 백준 15686번, 삼성 기출 문제

만두쓰 2022. 4. 20. 15:31

[문제]

 

[알고리즘]

  • BFS, 조합의 문제이다.
  • 입력 받은 치킨의 개수(M보다 크거나 같다) 중 선택할 치킨 M개를 선택한다. 
    • 백트래킹 방식을 사용한다.
  • BFS로 치킨집으로부터 각 집까지의 거리를 계산한다.

 

[느낀 점 / 깨달은 점]

  • 어제 풀었던 바이러스연구소 문제와 비슷하여 풀어보았다.
  • test case의 정답은 다 맞았지만, 자꾸만 채점 1%에서 틀렸습니다 결과가 나왔다.
    • 오류를 찾기 어려웠지만 찬찬히 코드를 본 결과, 백트래킹 부분에서 코딩 실수가 나왔다.
    • 아래 코드의 jj를 j로 잘못 쓴 코딩 실수였다. 
  • 조합을 풀 때 조심해야할 것은 현재의 위치보다 그 뒤 위치를 선택해야한다는 것이다. 
    • 나는 아래 코드와 같이 jj+1나 ii+1 처리를 해주었다. 이 처리를 안해주니 자꾸만 1개씩만 뽑힌 결과가 나왔다. 조심하자!

import copy 
import sys

def print_2darray(a):
    for i in a:
        for j in i:
            print(j, end=' ')
        print()
    print('--------')
    
def select_chicken(num, i, j):
    if num == M :
        # print("temp_city")
        # print_2darray(temp_city)
        bfs()
        return
    for ii in range(i, N):
        for jj in range(j, N):
            if city[ii][jj] == 2 : 
                temp_city[ii][jj] = 2
                if jj == N-1 :
                    select_chicken(num+1, ii+1, 0)
                else : 
                    select_chicken(num+1, ii, jj+1)
                temp_city[ii][jj] = 0
            j = 0

def bfs():
    from collections import deque

    dx = [0, 0, -1, 1]
    dy = [-1, 1, 0, 0]

    v = [[0] * N for _ in range(N)] 

    q = deque()
    for i in range(N):
        for j in range(N):
            if temp_city[i][j] == 2 : 
                q.append([i, j])

    num = 0
    while q :
        if num == num_house : 
            break
        
        i, j = q.popleft()

        for n in range(4):
            ii = i + dy[n]
            jj = j + dx[n]

            if ii < 0 or jj < 0 or ii >= N or jj >= N or temp_city[ii][jj] == 2 :
                continue
            elif  v[ii][jj] == 0 : 
                v[ii][jj] = v[i][j] +1
                q.append([ii,jj])
                if temp_city[ii][jj] == 1 :
                    num +=1

    global answer
    dist= 0
    for i in range(N):
        for j in range(N):
            if temp_city[i][j] == 1 : 
                dist += v[i][j]
    answer = min(answer, dist)

N, M = map(int, input().split())

city = [list(map(int, input().split())) for _ in range(N)]

temp_city = copy.deepcopy(city)
answer = sys.maxsize

num_house = 0
for i in range(N):
    for j in range(N):
        if city[i][j] == 2 : 
            temp_city[i][j] = 0
        if city[i][j] == 1 : 
            num_house +=1

select_chicken(0, 0, 0)
print(answer)