20058.魔法使いサメと火狐嵐
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に設定し,何度か失敗した.
上記の間違ったゲートに多くの時間を費やしましたが、コットを思うと怖いです.今後は上記のミスを減らす.
Reference
この問題について(20058.魔法使いサメと火狐嵐), 我々は、より多くの情報をここで見つけました
https://velog.io/@jin0106/20058.-마법사-상어와-파이어스톰
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
まず,メッシュを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に設定し,何度か失敗した.
上記の間違ったゲートに多くの時間を費やしましたが、コットを思うと怖いです.今後は上記のミスを減らす.
Reference
この問題について(20058.魔法使いサメと火狐嵐), 我々は、より多くの情報をここで見つけました
https://velog.io/@jin0106/20058.-마법사-상어와-파이어스톰
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
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)
問題を解決する過程で、いくつかのミスがあった.条件に合った氷-1の部分があり、それぞれの氷をチェックするたびにすぐ-1になると、もともと-1を必要としない氷も-1になります.また,ブロックの個数をカウントする場合,関数に入るとblockの値を0ではなく1に設定すべきであったが,最初は0に設定し,何度か失敗した.
上記の間違ったゲートに多くの時間を費やしましたが、コットを思うと怖いです.今後は上記のミスを減らす.
Reference
この問題について(20058.魔法使いサメと火狐嵐), 我々は、より多くの情報をここで見つけました https://velog.io/@jin0106/20058.-마법사-상어와-파이어스톰テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol