Algorithm(BOJ, Python)/BFS&DFS

[백준_22352] 항체인식 python

kurooru 2022. 9. 13. 13:02
# n, m 입력
n, m = map(int, input().split())

# case_before 입력
case_before = [
    list(map(int, input().split()))
    for _ in range(n)
]

# case_after 입력
case_after = [
    list(map(int, input().split()))
    for _ in range(n)
]
# 함수들
# test_2()
def test_2():
    
    # 색깔이 변한 횟수
    cnt = 0

    # 섹션의 대푯값들을 뽑기
    for section in sections:
        x, y = section[0]
        if case_before[x][y] != case_after[x][y]:
            cnt += 1
    
    # 두 섹션 이상에서 색깔이 변했으면,
    if cnt >= 2:
        # 실패
        return False
    
    # 다 통과했으면 성공
    return True

# test_1()
def test_1():
    # sections 안의 각 구역들을 꺼내
    for section in sections:
        for i in range(len(section) - 1):
            x, y = section[i]
            nx, ny = section[i+1]
            # 한번이라도 서로 숫자가 다르면
            if case_after[x][y] != case_after[nx][ny]:
                # 실패
                return False
    
    # 다 꺼냈는데 똑같으면 성공
    return True

# in_range(x, y)
def in_range(x, y):
    return 0 <= x < n and 0 <= y < m

# can_spread(x, y)
def can_spread(x, y):
    # 범위 내에 있고, 방문한 적 없으면 가능
    return in_range(x, y) and not visited[x][y]

# bfs()
def bfs():

    global curr_section

    while q:
        x, y = q.popleft()
        dxs, dys = [-1, 1, 0, 0], [0, 0, -1, 1]
        for dx, dy in zip(dxs, dys):
            nx, ny = x + dx, y + dy
            # 퍼질 수 있으면
            if can_spread(nx, ny) and case_before[x][y] == case_before[nx][ny]:
                # 큐에 넣어주고
                q.append((nx, ny))
                # 방문 처리 해 주고
                visited[nx][ny] = 1
                # curr_section에 넣어주기
                curr_section.append((nx, ny))

# find(x, y)
def find(x, y):
    
    global curr_section

    # 현재 연결된 좌표들을 관리해 줄 리스트
    curr_section = []

    # 큐에 넣어주고
    q.append((x, y))
    # 방문 처리 해 주고
    visited[x][y] = 1
    # 현재 좌표에도 넣어주고
    curr_section.append((x, y))
    # bfs 돌려주기
    bfs()

    # 전체 좌표 리스트에 넣어주기
    sections.append(curr_section)

# 설계
# 큐 사용준비
from collections import deque
q = deque()

# 구역들의 좌표를 구분하여 기록해 둘 리스트
sections = []

# visited
visited = [
    [0] * m
    for _ in range(n)
]

# case_before을 돌면서,
for i in range(n):
    for j in range(m):
        # 방문하지 않은 칸을 만나면,
        if not visited[i][j]:
            # 이와 연결된 좌표들을 찾아,
            # 한 구역으로 sections에 넣어주는 함수
            find(i, j)

# test_1과 test_2를 통과하면,
if test_1() and test_2():
    print('YES')
# 통과하지 못하면
else:
    print('NO')