16946_벽 부수고 이동하기 4
벽 부수고 이동하기
문제
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이 변을 공유할 때, 인접하다고 한다.
각각의 벽에 대해서 다음을 구해보려고 한다.
- 벽을 부수고 이동할 수 있는 곳으로 변경한다.
- 그 위치에서 이동할 수 있는 칸의 개수를 세어본다.
- 한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.
입력
첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다.
출력
맵의 형태로 정답을 출력한다. 원래 빈 칸인 곳은 0을 출력하고, 벽인 곳은 이동할 수 있는 칸의 개수를 10으로 나눈 나머지를 출력한다.
예제 입력 1
3 3
101
010
101예제 출력 1
303
050
303
Concept
- bfs,,,bfs!!bfs!!bfs!!!!!!!!! (틀렸다...ㅋㅋ)
- 실행시간 초과..
- 실행시간 초과 이유 : 모든 원소? 해당하는 벽? '1'인 원소에서 계속 BFS탐색을 시도하니,, 상당히 오래걸리는 작업이 된다.
- 그렇다면,, BFS를 최소한으로 사용하려면?
- 관점을 뒤바꾸어 생각하도록한다.
- 통과되어 있는 벽들이 연결되어 있는 개수를 저장...
- 연결되어 있는 벽들마다 연결되어 있는 개수가 다르므로, 서로 구별하여 저장을 하여야 하고, 이를 dictionary형태로 저장한다.
- 이렇게 되면 BFS탐색을 많이 할 필요가 없음..(방문한 정보를 저장하므로 이전에 방문했던 곳을 skip하므로)
- FloodFill algorithm 이라고 함.
- 이 후, '1'이라는 벽에서 자기 주변에 연결되어 있는 벽들의 정보를 모두 더하면 됨.
Code
def bfs(i,j,num):
cnt = 1
graph[i][j] = num
Q = []
Q.append((i,j))
while(Q):
curr = Q.pop()
for i in range(4):
new_x, new_y = curr[0]+move[i][0], curr[1]+move[i][1]
if((0<= new_x <n) and (0<= new_y <m) and visit[new_x][new_y]==False and graph[new_x][new_y]==0):
visit[new_x][new_y] = True
graph[new_x][new_y] = num
Q.append((new_x,new_y))
cnt += 1
return cnt
def check(row,col, dic):
what = set()
for i in range(4):
new_row, new_col = row+move[i][0], col+move[i][1]
if((0<= new_row < n) and (0<= new_col<m) and graph[new_row][new_col]!= 1):
what.add(graph[new_row][new_col])
cnt = 1
for i in what:
cnt += dic[i]
return cnt
n, m = map(int,input().split())
graph = [[]for _ in range(n)]
for i in range(n):
graph[i] = list(map(int, input()))
move = ((-1,0),(1,0),(0,-1),(0,1))
dic = {}
visit = [[False for _ in range(m)] for _ in range(n)]
num = 2
for i in range(n):
for j in range(m):
if(not visit[i][j] and not graph[i][j]):
dic[num] = bfs(i,j,num)
num+=1
answer = [[0]*m for _ in range(n)]
for i in range(n):
for j in range(m):
if(graph[i][j] == 1):
answer[i][j] = check(i,j, dic)%10
for i in range(n):
for j in range(m):
print(answer[i][j],end = '')
print()
참고
- 파이썬은,, 음.. 굳이 global선언을 안해도, 전역변수를 잘 가져와서 사용함. 아마 함수 밖에서 작성하는것은 다 global로 처리하는 듯..
- 왜 입장을 바꿔 사용하는 BFS탐색이 조금 더 빠른지 고민할 수 있었던 문제..
Author And Source
이 문제에 관하여(16946_벽 부수고 이동하기 4), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yoon_s_whan/16946벽-부수고-이동하기-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)