코딩테스트/파이썬

[백준/2468/파이썬] 안전 영역 (Python, dfs)

JI NY 2023. 3. 17. 22:42

[백준/2468/파이썬] 안전 영역 (Python, dfs)

2468번: 안전 영역 (acmicpc.net)

 

코드 1 (함수 x)

from sys import stdin,setrecursionlimit
import copy # 복사
input = stdin.readline

# 변수 정의
depth_arr = []  # 입력 깊이 배열
depth_arr2 = []  # 비교할 입력 길이
safe_arr = [] # 안전지대 개수
depth_max = 0 # 최대 깊이
depth = 4

# 입력
N = int(input()) 

#재귀 깊이 늘리기
setrecursionlimit(N*N+10)
# array 추가
for i in range(N):
    depth_arr.append(list(map(int, input().split())))
    depth_max = max(depth_arr[i]) # 최대 깊이 구하기


def dfs(x,y): #(행, 열)
    #주어진 범위를 벗어나는 경우에는 늑시 종료
    if x <= -1 or x >= N or y<= -1 or y>= N:
        return False
    
    if depth_arr2[x][y] == 0: #만약 방문하지 않았다면, ==0
        # 해당 노드 방문 처리
        depth_arr2[x][y] = 1
        #상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출 
        dfs(x-1, y) # 상 (행-1, 열)
        dfs(x, y-1) # 좌 (행, 열-1)
        dfs(x+1, y) # 하 (행+1, 열)
        dfs(x, y+1) # 우 (행, 열+1)
        return True
    return False # 만약, 이미 방문했다면 False


for k in range(0, depth_max+1): #1~ depth_max까지
# depth만큼 진행 ( 이건 나중에)
    depth_arr2 = copy.deepcopy(depth_arr)  # 리스트 복사

    #depth 이하이면, 1로배열 넣기
    for i in range(N):
        for j in range(N):
            if(depth_arr[i][j] <= k ): # 만약 높이가 장마 depth이하라면, 
                depth_arr2[i][j] = 1 # 물에 잠겼다
            else:
                depth_arr2[i][j] = 0 # 물에 잠기지 않았다.

    # print(depth_max)
    # print(depth_arr)
    # print(depth_arr2)



    # 노드 전체 방문
    count = 0
    for i in range(N):
        for j in range(N):
            if dfs(i,j) == True: # 새로 방문했다면
                count+= 1 # count++
    safe_arr.append(count)
print(max(safe_arr))

코드2 (함수1)

from sys import stdin,setrecursionlimit
import copy # 복사
input = stdin.readline

# 변수 정의
depth_arr = []  # 입력 깊이 배열
depth_arr2 = []  # 비교할 입력 길이
safe_arr = [] # 안전지대 개수
depth_max = 0 # 최대 깊이


# 입력
N = int(input()) 

#재귀 깊이 늘리기
setrecursionlimit(N*N+10)
# array 추가
for i in range(N):
    depth_arr.append(list(map(int, input().split())))
    depth_max = max(depth_arr[i]) # 최대 깊이 구하기


def dfs(x,y,dfsgraph): #(행, 열)
    #주어진 범위를 벗어나는 경우에는 늑시 종료
    if x <= -1 or x >= N or y<= -1 or y>= N:
        return False
    
    if dfsgraph[x][y] == 0: #만약 방문하지 않았다면, ==0
        # 해당 노드 방문 처리
        dfsgraph[x][y] = 1
        #상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출 
        dfs(x-1, y,dfsgraph) # 상 (행-1, 열)
        dfs(x, y-1,dfsgraph) # 좌 (행, 열-1)
        dfs(x+1, y,dfsgraph) # 하 (행+1, 열)
        dfs(x, y+1,dfsgraph) # 우 (행, 열+1)
        return True
    return False # 만약, 이미 방문했다면 False

def hing():
    for k in range(0, depth_max+1): #1~ depth_max까지
    # depth만큼 진행 ( 이건 나중에)
        dfsgraph = copy.deepcopy(depth_arr)  # 리스트 복사

        #depth 이하이면, 1로배열 넣기
        for i in range(N):
            for j in range(N):
                if(depth_arr[i][j] <= k ): # 만약 높이가 장마 depth이하라면, 
                    dfsgraph[i][j] = 1 # 물에 잠겼다
                else:
                    dfsgraph[i][j] = 0 # 물에 잠기지 않았다.

        # 노드 전체 방문
        count = 0
        for i in range(N):
            for j in range(N):
                if dfs(i,j,dfsgraph) == True: # 새로 방문했다면
                    count+= 1 # count++
        safe_arr.append(count)

hing()
# print(safe_arr)
print(max(safe_arr))

풀이

  • N을 입력받는다.
  • 2차원리스트로 각 요소를 추가한다.
    • 이때 최대 장마 비 깊이를 구한다. (max)
  • dfs 구현
  • 0부터 최고 깊이까지 반복한다.  
    • 원본 리스트를 복사한다 (deepcopy 사용) (=으로 리스트를 넣어버리면 포인터처럼 가리키게 되어 버려서 copy함수를 써야 한다.)
    • 원본리스트의  각 요소에 장마 높이(depth)만큼 비교하면서, 물에 잠겼으면 복사리스트 요소를 1로 만들고, 물에 잠기지 않았으면 복사리스트를 0으로 만든다.
      • 이렇게 0,1로 된 복사 리스트를 만들었다
    • 2중 for문으로 복사 리스트의 모든 노드(i, j)를 방문하며 dfs를 돌린다.
      • 새로 방문한 곳이 생기면, count +=1 한다.
    • 안전지대 개수(safe_arr) 리스트에 count를 append 한다.
  • 반복이 끝난 뒤, 안전지대 개수 리스트(safe_arr)의 최댓값을 프린트한다. 그러면 0부터 최대 깊이까지 안전지대를 비교한 것 중 가장 많은 안전지대가 나온 것을 출력해 준다.

후기

다음에 다시 풀어봐야겠다.

시간 소요는 약 3시간 30분 걸렸다 

나동빈 님의 강의와 코드를 참고했다

( (1) (이코테 2021 강의 몰아보기) 3. DFS & BFS - YouTube )

deep copy라는 것도 알게 됐다.

a = list_a 이렇게 복사해 버리면, a가 list_a를 포인터처럼 가리키는 것도 알게 됐다.

( [기능] 파이썬 리스트 복사 (python copy) :: 검정이 (tistory.com) )

 

또한 pypy로 이 코드를 돌리면 메모리초과가 나오고, 파이썬으로 돌리면 제대로 나오는 걸 보고, 파이파이가 상대적으로 메모리가 작구나라고 생각했다.

dfs 얼른 마스터하고 싶다!