python-for-coding-test icon indicating copy to clipboard operation
python-for-coding-test copied to clipboard

p.341 연구소 문제 풀이 중 이해가 안 가는 부분 질문입니다!

Open iamcodingcat opened this issue 4 years ago • 0 comments

책 풀이 중에 마지막 하단의 코드 부분에서 어떻게 3개의 벽을 설치하는 모든 경우의 수를 탐색하나요?

for i in range(n):
    for j in range(m):
        # 빈 공간에만 벽을 설치할 수  있음
        if data[i][j] == 0:
            data[i][j] = 1   # 벽 설치
            count += 1  # 설치한 벽 수 +1
            dfs(count)       
            data[i][j] = 0
            count -= 1  # 복구한 벽을 설치한 벽 수에서 -1 차감

그래서 제가 아래의 일일이 출력하는 코드까지 작성해서 해보았는데 결과화면에서 이상한 점을 발견했는데요? 아래와 같이 인풋 데이터가 주어졌다고 할 때, 최초의 벽은 (0, 0) , (0, 1) , (1, 1) 위치에 순차적으로 벽을 설치하고 안전영역 계산 후에 (1, 1) 위치의 벽을 허물고 난 후 (1, 2) 위치에 벽을 설치하고 ... (반복) 하잖아요? 이렇게 (0, 0), (0, 1) 벽 설치를 고정시키고 주어진 범위 안에서 설치할 수 있는 벽 위치의 마지막 값인 (1, 2)위치의 벽을 설치하고 난 후 안전영역 계산 후 (1, 2) 위치의 벽을 허문다음 갑자기 (0, 1)의 벽을 허무는데요? 이 부분이 이해가 안갑니다. 갑자기 연속으로 2번 허물게 되는 로직이 어디서 발생하는 건가요? 만약 (0, 1)의 벽을 허물려면 data[0][1] == 0의 조건을 만족해야 하는데, 현재는 (0, 1) 위치에 벽이 설치(data[0][1] = 1 이기 떄문)되었기 때문에 i=0, j=1 일 때, 벽을 허무는 조건문으로 들어갈 수 없지 않나요? 답변 아시면 꼭 부탁드립니다... 꼭 이해해보고 싶네요.. 어떤 점을 제가 오해하고 있는지 알려주시면 감사하겠습니다! 이거는 제가 의심하는 부분의 출력 결과 화면이고 그 아래는 해당 출력 결과를 출력하는 코드 입니다. 스크린샷 2021-09-27 오후 5 33 50

import numpy as np

n, m = map(int, input().split())
data = []  # 주어지는 맵 정보 담을 리스트
temp = [[0] * m for _ in range(n)]  # 주어진 맵 정보 + 설치한 벽 3개 반영할 리스트
for _ in range(n):
    data.append(list(map(int, input().split())))

# 4가지 이동 방향
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

result = 0  # 안전영역 계산 초기값

# 1. 바이러스 퍼지는 공간을 DFS로 탐색
def virus_dfs(x, y):
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0 <= nx < n and 0 <= ny < m:
            # 전파시키려고 하는 곳이 빈 공간이면 전염
            if temp[nx][ny] == 0:
                temp[nx][ny] = 2
                # 재귀적으로 DFS
                virus_dfs(nx, ny)

# 2. 주어진 맵 정보와 새로운 벽 3개 설치 후 바이러스 전파시킨 후 안전영역 계산 함수
def get_score():
    score = 0
    for i in range(n):
        for j in range(m):
            if temp[i][j] == 0:
                score += 1
    return score

# 3. 벽 설치하는 경우의 수를 DFS로 탐색하면서 1번 경우의 수마다 바이러스 전파 및 안전영역 계산 -> 경우의 수 탐색할 때마다 안전영역 최댓값 업데이트
def dfs(count):
    print('dfs가 실행되었어요!', 'count:', count)
    global result
    # 설치한 벽 개수가 3개 도달했을 때
    if count == 3:
        # 주어진 맵 정보 & 새로 설치한 벽 3개 정보를 -> temp 리스트에다가 반영 for 안전영역 계산하기 위해
        for i in range(n):
            for j in range(m):
                temp[i][j] = data[i][j]

        # 업데이트 된 맵 temp를 일일이 돌면서 바이러스일 때 전파 함수 수행
        for i in range(n):
            for j in range(m):
                if temp[i][j] == 2:
                    virus_dfs(i, j)
        # 바이러스 전파 모두 끝난 후 안전영역 계산 및 기존 안전영역과 업데이트
        result = max(result, get_score())
        return

    # 3개 벽을 설치하는 경우의 수를 DFS로 탐색
    # 처음에 돌 때는 (i=0, j=0)으로 고정하고 재귀함수를 다 돌은 다음, 끝에 도달하면 (i=0, i=1
    for i in range(n):
        for j in range(m):
            # 빈 공간에만 벽을 설치할 수  있음
            if data[i][j] == 0:
                print('='*50)
                print('새로 설치한 벽:', (i, j))
                data[i][j] = 1   # 벽 설치
                count += 1  # 설치한 벽 수 +1
                print(np.array(data))
                dfs(count)       # 재귀적으로 수행하면서 위에서 벽 설치한 공간(1) 말고 다른 설치할 수 있는 공간에다가 다른 벽 설치
                data[i][j] = 0   # 마지막에 설치한 벽 복구?
                count -= 1  # 복구한 벽을 설치한 벽 수에서 -1 차감
                print('-'*50)
                print('취소한 벽:', (i, j))
                print(np.array(data))



dfs(0)
print(result)

iamcodingcat avatar Sep 26 '21 11:09 iamcodingcat