fire_storm
함수를 호출tmp_arr
을 생성한 뒤 구역탐색을 시작section
배열을 생성한 뒤 해당 위치에 대한 값을 저장section
을 회전tmp_arr
에 저장section
에 대한 값이 tmp_arr
에 저장이 되었다면 melt
함수를 실행result_arr
리스트를 생성한 뒤 배열 순회result_arr
에 저장arr
배열을 갱신📌 pypy로 통과했다
마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다.
오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다.
위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 얼음의 양을 의미한다.
A[r][c]가 0인 경우 얼음이 없는 것이다.
파이어스톰을 시전하려면 시전할 때마다 단계 L을 결정해야 한다.
파이어스톰은 먼저 격자를 2L × 2L 크기의 부분 격자로 나눈다.
그 후, 모든 부분 격자를 시계 방향으로 90도 회전시킨다.
이후 얼음이 있는 칸 3개 또는 그 이상과 인접해있지 않은 칸은 얼음의 양이 1 줄어든다.
(r, c)와 인접한 칸은 (r-1, c), (r+1, c), (r, c-1), (r, c+1)이다.
아래 그림의 칸에 적힌 정수는 칸을 구분하기 위해 적은 정수이다.
마법사 상어는 파이어스톰을 총 Q번 시전하려고 한다.
모든 파이어스톰을 시전한 후, 다음 2가지를 구해보자.
남아있는 얼음 A[r][c]의 합
남아있는 얼음 중 가장 큰 덩어리가 차지하는 칸의 개수
얼음이 있는 칸이 얼음이 있는 칸과 인접해 있으면, 두 칸을 연결되어 있다고 한다.
덩어리는 연결된 칸의 집합이다.
import sys
input = sys.stdin.readline
dx, dy = [-1, 1, 0, 0], [0, 0, -1, 1]
def fire_storm(spell):
global arr
tmp_arr = [[0] * 2 ** N for _ in range(2 ** N)]
for start_x in range(0, 2 ** N, spell):
for start_y in range(0, 2 ** N, spell):
section = [[0] * spell for _ in range(spell)]
for i in range(spell):
for j in range(spell):
section[i][j] = arr[start_x + i][start_y + j]
section = rotate(section)
for i in range(spell):
for j in range(spell):
tmp_arr[start_x + i][start_y + j] = section[i][j]
arr = melt(tmp_arr)
return
def rotate(section):
return [list(elem) for elem in zip(*section[::-1])]
def melt(tmp_arr):
result_arr = [[0] * (2 ** N) for _ in range(2 ** N)]
for i in range(2 ** N):
for j in range(2 ** N):
if tmp_arr[i][j]:
cnt = 0
for k in range(4):
nx, ny = i + dx[k], j + dy[k]
if 0 <= nx < 2 ** N and 0 <= ny < 2 ** N:
if tmp_arr[nx][ny]:
cnt += 1
result_arr[i][j] = tmp_arr[i][j] - 1 if cnt < 3 else tmp_arr[i][j]
return result_arr
def sum_ice():
total = 0
for i in range(2 ** N):
for j in range(2 ** N):
if arr[i][j]:
total += arr[i][j]
return total
def block_length():
visited = [[False] * (2 ** N) for _ in range(2 ** N)]
max_length = 0
for i in range(2 ** N):
for j in range(2 ** N):
if arr[i][j] and visited[i][j] == False:
visited[i][j] = True
length = 0
stack = [(i, j)]
while stack:
x, y = stack.pop()
length += 1
for k in range(4):
nx, ny = x + dx[k], y + dy[k]
if 0 <= nx < 2 ** N and 0 <= ny < 2 ** N:
if arr[nx][ny] and visited[nx][ny] == False:
visited[nx][ny] = True
stack.append((nx, ny))
max_length = max(max_length, length)
return max_length
N, Q = map(int, input().split())
arr = [list(map(int, input().split())) for _ in range(2 ** N)]
spells = list(map(int, input().split()))
for spell in spells:
fire_storm(2 ** spell)
print(sum_ice())
print(block_length())