상세 컨텐츠

본문 제목

[백준 16946번] 벽 부수고 이동하기4(파이썬)

알고리즘 공부

by Tabris4547 2022. 8. 22. 12:02

본문

728x90

https://www.acmicpc.net/problem/16946

16946번: 벽 부수고 이동하기 4

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이

www.acmicpc.net

처음 이 문제를 만났을 때에는
'이게 골드2?
이거 골드 5수준이잖아?'
하면서 쉽게 생각했습니다.
그리고 제출하자마자 시간초과.

제가 생각한 방식은 간단했습니다.
'지도돌다가 1만나면 거기서 bfs해준다'
이렇게 하면 예제는 통과하지만
시간초과가 납니다.
그리고 시간초과가 뜰 때
내가 뭘 생각하지 못하는구나 깨닫고 힌트를 얻어봤습니다.

https://ku-hug.tistory.com/153

[Python/파이썬] 백준 16946번: 벽 부수고 이동하기 4

문제 풀이 1. 0의 묶음을 그룹으로 표시해준다. 2. 각 그룹별로 0의 개수가 몇 개인지 dict를 통해 저장한다. 3. 벽(1)에서 상하좌우로 인접한 그룹을 구한 뒤, 그 그룹에 해당하는 0의 개수를 더해준

ku-hug.tistory.com

아이디어는 바로
0을 미리 묶어준다입니다.
0을 그룹으로 묶은 후에
1를 만날때
'어떤 그룹과 인접하는지'
구한 후에
0의 갯수를 구하면
최소한 위에서 말한 1을 계속bfs해주는 방식보다는
시간 소요가 줄어듭니다.

#백준 16946번 벽 부수고 이동하기4
from collections import deque

dx=[0,0,1,-1]
dy=[1,-1,0,0]


N,M=map(int,input().split())
room=[]
for _ in range(N):
    put=input()
    tmp=[]
    for j in range(M):
        tmp.append(int(put[j]))

    room.append(tmp)


way=[[0]*M for _ in range(N)]
group=[[-1]*M for _ in range(N)]
mung=[0]*(M*N)
#1. 0을 각각 그룹화한다
numbers=0
visited = [[False] * M for _ in range(N)]
for x in range(N):
    for y in range(M):
        if room[x][y]==0 and visited[x][y]==False:
            cnt=1
            visited[x][y]=True
            q=deque()
            q.append([x,y])
            group[x][y]=numbers
            while q:
                px,py=q.popleft()

                for d in range(4):
                    nx=px+dx[d]
                    ny=py+dy[d]

                    if nx<0 or nx>=N or ny<0 or ny>=M:
                        continue
                    if visited[nx][ny]==True:
                        continue

                    if room[nx][ny]==1:
                        continue
                    if group[nx][ny]>=0:
                        continue

                    q.append([nx,ny])
                    visited[nx][ny]=True
                    group[nx][ny]=numbers
                    cnt+=1
            #mung이라는 리스트에 각각 넘버의 숫자를 넣음.
            mung[numbers]=cnt
            numbers+=1

#2 벽을 허물고 맡닺는 0의 갯수를 본다
for x in range(N):
    for y in range(M):
        if room[x][y]==0:
            continue
        way[x][y]+=1
        #집합으로 표시한 이유-->중복 없에기
        setting=set()
        for d in range(4):
            nx=x+dx[d]
            ny=y+dy[d]

            if nx<0 or nx>=N or ny<0 or ny>=M:
                continue

            if group[nx][ny]==-1:
                continue
            po=group[nx][ny]
            setting.add(po)

        for zero in setting:

            way[x][y]+=mung[zero]
        way[x][y]%=10

# for x in range(N):
#     print(" ".join(map(str,group[x])))
#
# print(mung)
for x in range(N):
    print("".join(map(str,way[x])))

pypy3로 통과한 코드입니다.

이 문제의 아이디어가 상당히 좋았습니다.
bfs를 구할 때
다른 관점에서 접근하는 걸 배웠습니다.

728x90

관련글 더보기

댓글 영역