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개의 댓글