20058. 마법사 상어와 파이어스톰

Jin·2021년 11월 11일
0

baekjoon

목록 보기
5/5
post-thumbnail

1. 문제소개 및 문제 출처

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

2. 해결 과정

먼저 문제에 나와있는데로 격자를 어떻게 구분하여 그 격자만큼 90도 회전을 시켜줄지 고민을 하였다. 단순 90도 회전이었으면 쉬웠을텐데, 격자로 구분을 한뒤 그 안에서 90도 회전을 해줘야했기 때문에 이부분에서 시간이 오래 걸렸다. 예전에 스도쿠 문제를 풀었던게 이 부분에서 도움이 되었던것 같다.
그 이후, deque와 bfs를 사용하여 인접해있는 칸 확인과 덩어리의 확인을 해주었다.

3. 코드

from collections import deque

# 90도 회전하기
def rotate():
    global ices
    # 격자범위
    lth = 2**l
    # 임시 얼음판
    temp = [[0]*(n) for _ in range(n)]

    for y in range(0,n,lth):
        for x in range(0,n,lth):
            for i in range(lth):
                for j in range(lth):
                    temp[y+j][x+(lth-1)-i] = ices[y+i][x+j]
    # 얼음 재지정
    ices = temp

# 제거하기
def remove():
    # 한번에 제거하기 위해 빈 리스트 생성
    temp = []

    for y in range(n):
        for x in range(n):
            cnt = 0
            for i in range(4):

                ny = y + dr[i]
                nx = x + dc[i]
                if 0 <= ny < n and 0 <= nx < n:
                    if ices[ny][nx]>0:
                        cnt +=1
            # cnt 3미만이면 1빼줘야 하므로 temp에 좌표 추가
            if cnt >=3:
                continue
            else:
                temp.append((y,x))

    # 한번에 빼주기
    for y,x in temp:
        ices[y][x] -=1

# 덩어리 구하기
def bfs(y,x):
    global min_block

    # 처음 y,x 좌표에도 얼음이 있으므로 1로 설정
    block = 1
    q = deque()
    q.append((y,x))

    while q:
        y,x = q.popleft()
        for i in range(4):
            ny = y + dr[i]
            nx = x + dc[i]
            if 0 <= ny < n and 0 <= nx < n and visited[ny][nx]==0:
                visited[ny][nx]=1
                if ices[ny][nx]>0:
                    block +=1
                    q.append((ny,nx))
    # q가 빈 리스트가 되면 연결되는것 다 더했다는 뜻이므로 최대값인지 비교
    if min_block < block:
        min_block = block

    return


dr = [-1,1,0,0]
dc = [0,0,-1,1]

N, Q = map(int, input().split())
n = 2**N
ices = [list(map(int, input().split())) for _ in range(2**N)]
L = list(map(int, input().split()))

min_block = 0
for i in range(Q):
    l = L[i]
    rotate()
    remove()



ans = 0

# 방문 기록
visited = [[0]*n for _ in range(n)]

# 남은 얼음 갯수 구하면서 최대 덩어리 구하기
for y in range(n):
    for x in range(n):
        if ices[y][x]>0:
            ans += ices[y][x]
        if visited[y][x] ==0 and ices[y][x]>0:
            visited[y][x] =1
            bfs(y,x)
print(ans)
print(min_block)

4. 느낀점 및 배운점

문제를 해결하는 과정에서 몇가지 실수들이 있었다. 조건에 맞는 얼음을 -1 해주는 부분이 있었는데 얼음하나하나를 체크할때마다 바로 -1을 해주면 원래 -1 되지 않아도 되는 얼음들까지 -1되버린다. 그리고 덩어리의 갯수를 카운트 할 때 함수에 들어가면 block의 값을 0이 아닌 1로 설정을 해줬어야했는데, 처음에 0으로 설정을 해줘 몇 번 실패를 했었다.
위와 같은 실수들 대문에 시간을 많이 할애하였는데, 코테라고 생각하면 끔찍하다.. 앞으로 위와 같은 실수들을 줄이도록 해야겠다.

profile
내가 다시 볼려고 작성하는 블로그

0개의 댓글