문제
차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. 한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있는 것이다.
한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어 놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다. 예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다. 0은 배추가 심어져 있지 않은 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.

입력
입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 첫째 줄에는 배추를 심은 배추밭의 가로길이 M(1 ≤ M ≤ 50)과 세로길이 N(1 ≤ N ≤ 50), 그리고 배추가 심어져 있는 위치의 개수 K(1 ≤ K ≤ 2500)이 주어진다. 그 다음 K줄에는 배추의 위치 X(0 ≤ X ≤ M-1), Y(0 ≤ Y ≤ N-1)가 주어진다. 두 배추의 위치가 같은 경우는 없다.
출력
각 테스트 케이스에 대해 필요한 최소의 배추흰지렁이 마리 수를 출력한다.

풀이
풀이 1 (DFS-167332KB, 240ms)
import sys
sys.setrecursionlimit(10000)
T = int(input())
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1] # 방향 벡터 / 상하좌우 4방향
# 해당 위치가 땅을 넘어서는지 확인
def check(x, y):
if x < 0 or x > N - 1 or y < 0 or y > M - 1:
return False
return True
def dfs(x, y):
for d in range(4): # d = direction
x_, y_ = x + dx[d], y + dy[d]
if check(x_, y_):
# 배추가 심어져 있으면, 1을 0으로 바꿈. (확인한 것을 표시)
if cabbage[x_][y_] == 1:
cabbage[x_][y_] = 0
dfs(x_, y_)
for _ in range(T):
M, N, K = map(int, input().split())
cabbage = [[0] * M for _ in range(N)]
for _ in range(K):
y, x = map(int, input().split()) # 배열의 세로를 x, 가로를 y로 두기 위해서
# x => N, y => M / 그림 상, 세로가 x이자 N 값이고, 가로가 y이자 M값임
cabbage[x][y] = 1
cnt = 0 # cnt=count, 배추흰지렁이 카운팅
# dfs 사용
for i in range(N):
for j in range(M):
if cabbage[i][j] == 1:
cnt += 1
dfs(i, j)
print(cnt)
- 배추가 덩어리로써 서로 인접해 있으면, 그곳에 지렁이 한 마리를 놔두게 됨. (예시에서 배추를 5 덩어리로 볼 수 있음) 상하좌우에 배추가 있어서 한 번 이동하면 끝이 아니라, 배추가 서로 인접해있으면 지렁이가 계속 움직일 수 있음(그런 의미에서 한 덩어리)
- 배열을 i, j로 읽으면서 1을 만나면 dfs 함수를 시작해서 인접한 1을 모두 0으로 만든 뒤, 지렁이 1마리를 카운트함. (= cnt + 1)
- check 함수는 dfs로 탐색을 할 때, 그 위치가 땅을 벗어나는지 확인함.
- dfs의 재귀 깊이에 대한 제한을 늘리기 위해 sys.setrecursionlimit(10000)을 사용함. 아니면 런타임 에러가 발생함.
풀이 2 (BFS-115456KB, 164ms)
T = int(input())
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1] # 방향벡터 상하좌우 4방향
# 위치를 확인하니 배추가 1이면(있으면) BFS 진행
def bfs(x, y):
# 큐에 배추 위치를 쌓고, 1을 0으로 바꿀 것
queue = [(x, y)]
cabbage[x][y] = 0
while queue:
x, y = queue.pop(0)
for d in range(4):
x_, y_ = x + dx[d], y + dy[d]
# 땅을 벗어난 경우, 무시
if x_ < 0 or x_ > N - 1 or y_ < 0 or y_ > M - 1:
continue
# 옆을 확인하니 배추가 있는 경우, 위치를 큐에 쌓고, 1을 0으로 바꿈
if cabbage[x_][y_] == 1:
queue.append((x_, y_))
cabbage[x_][y_] = 0
for _ in range(T):
M, N, K = map(int, input().split())
cabbage = [[0] * M for _ in range(N)]
for _ in range(K):
y, x = map(int, input().split()) # 배열의 세로를 x, 가로를 y로 두기 위해서
# x => N, y => M / 그림 상, 세로가 x이자 N 값이고, 가로가 y이자 M값임
cabbage[x][y] = 1
cnt = 0 # cnt=count, 배추흰지렁이 카운팅
for x in range(N):
for y in range(M):
if cabbage[x][y] == 1:
cnt += 1
bfs(x, y)
print(cnt)
- i, j 로 배열을 확인하다가 1을 발견하면 (=배추가 있으면), BFS 진행. (1을 0으로 바꾸면서)
출처
- 문제를 만든 사람: author2
'What is Computer? > Data structure & Algorithm' 카테고리의 다른 글
[Python] 백준 '꽃길' 14620번 | 방향 벡터, 브루트 포스, DFS 알고리즘 문제 (0) | 2022.10.11 |
---|---|
[Python] 백준 '늑대와 양' 16956번 | 방향벡터 알고리즘 문제 (0) | 2022.10.10 |
[Python] 백준 '친구 네트워크' 4195번 | 해시 Union-Find, 집합, 그래프 자료구조 문제 (0) | 2022.10.10 |
[Python] 백준 '수 찾기' 1920번| 해쉬, 배열, 구현 자료구조 (0) | 2022.10.10 |
[Python] 백준 'SHA-256' 10930번 | 해시, 구현 자료구조 문제 (0) | 2022.10.08 |