N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이 변을 공유할 때, 인접하다고 한다.
각각의 벽에 대해서 다음을 구해보려고 한다.
한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.
입력
- 첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다.
출력
- 맵의 형태로 정답을 출력한다. 원래 빈 칸인 곳은 0을 출력하고, 벽인 곳은 이동할 수 있는 칸의 개수를 10으로 나눈 나머지를 출력한다.
import sys
from collections import deque
input = sys.stdin.readline
# 0의 갯수를 세고, 어디에 소속되어 있는지 기록하는 함수
def count_zero(x,y,cluster_num):
global cluster
q = deque()
q.append((x,y))
cluster[y][x] = cluster_num
cnt = 1
while q:
a,b = q.popleft()
for i in range(4):
nx = a + dx[i]
ny = b + dy[i]
if(0<=nx<m and 0 <= ny <n):
if cluster[ny][nx]==0 and grid[ny][nx] == 0:
cluster[ny][nx] = cluster_num
q.append((nx,ny))
cnt += 1
return cnt
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int,input().strip())))
# 각 클래스터 그룹 번호 = 인덱스 기준 , 0의 갯수 기록
cluster_record = [0]
# 클러스터 넘버링
cluster_num = 1
# 그리드로 클러스트 그룹별 번호 기록
cluster = [[0]*m for _ in range(n)]
# 상하좌우 설정
dx = [-1,1,0,0]
dy = [0,0,-1,1]
# 0의 갯수를 세고, 어느 클러스터에 소속되어 있지 않다면 진행.
for x in range(m):
for y in range(n):
if grid[y][x] == 0 and cluster[y][x] == 0 :
cnt_zero = count_zero(x,y,cluster_num)
cluster_record.append(cnt_zero%10)
cluster_num += 1
# 클러스터 그룹과 1을 부쉈을 때를 기준으로, grid를 새로 업데이트
for x in range(m):
for y in range(n):
if grid[y][x] == 1:
cluster_grid = set()
for a in range(4):
nx = x + dx[a]
ny = y + dy[a]
if (0<=nx<m and 0 <= ny <n):
cluster_grid.add(cluster[ny][nx])
for i in cluster_grid:
grid[y][x]+= cluster_record[i]
grid[y][x] %= 10
for y in grid:
for x in y:
print(x, end='')
print()
import sys
from collections import deque
input= sys.stdin.readline
n, m = map(int, input().split())
grid =[]
for _ in range(n):
a = list(map(int, input().strip())) # 공백으로 구분된 정수 입력 받기
grid.append(a)
# 상하좌우 설정
dx = [-1,1,0,0]
dy = [0,0,-1,1]
def dfs(x,y):
visited = [[False]*m for _ in range(n)]
q = deque()
q.append([x,y])
visited[y][x]= True
cnt = 1
while q:
a,b = q.popleft()
for i in range(4):
nx = a + dx[i]
ny = b + dy[i]
if (0<= nx < m and 0<= ny <n):
if grid[ny][nx] == 0 and not visited[ny][nx]:
q.append((nx,ny))
visited[ny][nx] = True
cnt += 1
return cnt%10
for y in range(n):
for x in range(m):
if grid[y][x]==1:
grid[y][x] = dfs(x,y)
for y in grid:
for x in y:
print(x,end='')
print()
그냥 간단하게 전부다 확인하면서 하면 될 줄 알았더니, 시간 복잡도가 O(n^3)이므로, 매우 안 좋다.
그렇기 때문에 시간 복잡도를 O(n^2)으로 줄일 필요가 있었고, 결국 아이디어를 하나 가져와서 풀게 되었다.
ㅎ...
보니까 매우 어렵다고 한다.
(사실 그전에 수많은 도전이 있었다... 시간 초과를 뚫기 위해...)
import sys
from collections import deque
input = sys.stdin.read
data = input().splitlines()
n, m = map(int, data[0].split())
grid = [list(map(int, line.strip())) for line in data[1:n+1]]
cluster_record = [0]
cluster_num = 1
cluster = [0] * (n * m)
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
def count_zero(x, y, cluster_num):
visited = [False] * (n * m)
q = deque()
q.append((x, y))
cluster[y * m + x] = cluster_num
visited[y * m + x] = True
cnt = 1
while q:
a, b = q.popleft()
for i in range(4):
nx = a + dx[i]
ny = b + dy[i]
if 0 <= nx < m and 0 <= ny < n:
if not visited[ny * m + nx] and grid[ny][nx] == 0:
visited[ny * m + nx] = True
cluster[ny * m + nx] = cluster_num
q.append((nx, ny))
cnt += 1
return cnt
for x in range(m):
for y in range(n):
if grid[y][x] == 0 and cluster[y * m + x] == 0:
cnt_zero = count_zero(x, y, cluster_num)
cluster_record.append(cnt_zero % 10)
cluster_num += 1
for x in range(m):
for y in range(n):
if grid[y][x] == 1:
cluster_grid = set()
for a in range(4):
nx = x + dx[a]
ny = y + dy[a]
if 0 <= nx < m and 0 <= ny < n:
cluster_grid.add(cluster[ny * m + nx])
for i in cluster_grid:
grid[y][x] += cluster_record[i]
grid[y][x] %= 10
for row in grid:
print(''.join(map(str, row)))
결론적으로 여기서 가장 큰 문제점은 기록을 하는데에, 시간을 너무 많이 잡아먹는다는 점이었다. 그렇기 때문에, 기록을 하는 대신, 클러스터에 기록함으로써, 기록과 어느 클러스터에 속해있는지 동시에 기록했다.
코드를 분석하면 무슨 내용인지 이해가 갈거라고 생각한다. ...
a = list(map(int, input().strip())) # 공백으로 구분된 정수 입력 받기
진짜 너무너무 어려웠다. 진심.