SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
일반적으로 deque를 써서 이동하면 되는 문제가 아니라
알고리즘을 구성하는데 애를 많이 먹었습니다.
가장 어려웠던 부분은
'군집이 합쳐지는 케이스'
만약 이 케이스가 없었더라면
그냥 bfs하듯이 q를 계속 돌렸을텐데
이 부분이 있어서 좀 골치아팠습니다.
#삼성sw 2382 미생물격리
from copy import deepcopy
dx=[0,-1,1,0,0]
dy=[0,0,0,-1,1]
T=int(input())
def move():
global room
day=0
while day<M:
new_room=[[[] for _ in range(N) ]for _ in range(N)]
hap=set()
for x in range(N):
for y in range(N):
if room[x][y]:
cnt=room[x][y][0][0]
direct=room[x][y][0][1]
nx=x+dx[direct]
ny=y+dy[direct]
if nx==0 or nx==N-1 or ny==0 or ny==N-1:
cnt//=2
if direct==1:
direct=2
elif direct==2:
direct=1
elif direct==3:
direct=4
elif direct==4:
direct=3
if cnt==0:
continue
new_room[nx][ny].append([cnt,direct])
if len(new_room[nx][ny])>1:
hap.add((nx,ny))
#겹친거 처리해주기
for hx,hy in hap:
now=new_room[hx][hy]
n_size=len(now)
n_cnt=now[0][0]
n_max=now[0][0]
n_dir=now[0][1]
for k in range(1,n_size):
if now[k][0]>n_cnt:
n_cnt=now[k][0]
n_dir=now[k][1]
n_max+=now[k][0]
new_room[hx][hy].clear()
new_room[hx][hy].append([n_max,n_dir])
room=deepcopy(new_room)
day+=1
for case in range(T):
N,M,K=map(int,input().split())
virus=[]
room =[[[] for _ in range(N) ]for _ in range(N)]
for _ in range(K):
vx,vy,vcnt,vdir=map(int,input().split())
room[vx][vy].append([vcnt,vdir])
move()
answer=0
for x in range(N):
for y in range(N):
if room[x][y]:
answer+=room[x][y][0][0]
print("#%d %d"%((case+1),answer))
처음에 제출했던 코드입니다.
문제에서 요구하는 데로 그대로 구현했습니다.
좌표를 돌면서 바이러스가 있는 걸 찾아서
계속 움직이는 방식이었죠.
하지만 for문을 너무 많이 돌다보니
시간초과를 피할 수 없었습니다.
어떻게 시간초과를 줄일까 생각하다가
'방 전체를 계속 돌기보다는
바이러스만 보고 움직이자'
라는 생각이 들어서 코드를 수정했습니다.
#삼성sw 2382 미생물격리
dx=[0,-1,1,0,0]
dy=[0,0,0,-1,1]
T=int(input())
def move():
global virus
day=0
while day<M:
new_room=[[[] for _ in range(N) ]for _ in range(N)]
hap=set()
popping=[]
#1 바이러스를 움직여준다
for k in range(len(virus)):
now_virus=virus[k]
x,y,cnt,dir=now_virus
nx=x+dx[dir]
ny=y+dy[dir]
if nx==0 or nx==N-1 or ny==0 or ny==N-1:
n_cnt=cnt//2
#나눠서 0이 되는 건 나중에 삭제해준다
if n_cnt==0:
popping.append([x,y,cnt,dir])
continue
if dir==1:
n_dir=2
elif dir==2:
n_dir=1
elif dir==3:
n_dir=4
elif dir==4:
n_dir=3
else:
n_cnt=cnt
n_dir=dir
new_room[nx][ny].append([n_cnt,n_dir])
#이동한 구역에 바이러스가 2개이상이라면 hap이라는 집합에 넣어준다
if len(new_room[nx][ny])>=2:
hap.add((nx,ny))
virus[k]=[nx,ny,n_cnt,n_dir]
#2. 군집이 겹치는 거 처리해주기
for hx,hy in hap:
now=new_room[hx][hy]
now_cnt=now[0][0]
now_max=now[0][0]
now_dir=now[0][1]
popping.append([hx,hy,now_cnt,now_dir])
#군집의 방향을 결정+군집의 모든 바이러스 합 구하기
for i in range(1,len(now)):
if now[i][0]>now_max:
now_max=now[i][0]
now_dir=now[i][1]
now_cnt+=now[i][0]
#이전 군집에 있는 바이러스는 없애준다
popping.append([hx,hy,now[i][0],now[i][1]])
#다 구한 군집의 바이러스,방향을 넣어준다
virus.append([hx,hy,now_cnt,now_dir])
#3. 없앨 바이러스는 없애준다
for px,py,p_cnt,p_dir in popping:
p_ind=virus.index([px,py,p_cnt,p_dir])
virus.pop(p_ind)
day+=1
for case in range(T):
N,M,K=map(int,input().split())
virus=[]
room =[[[] for _ in range(N) ]for _ in range(N)]
for _ in range(K):
vx,vy,vcnt,vdir=map(int,input().split())
virus.append([vx,vy,vcnt,vdir])
move()
answer=0
for k in range(len(virus)):
answer+=virus[k][2]
print("#%d %d"%((case+1),answer))
시간초과를 어떻게 줄일 수 있을지
공부할 수 있게 만들어준 좋은 문제입니다.
[백준 9328번] 열쇠(파이썬) (0) | 2022.09.28 |
---|---|
[백준 5022번] 연결(파이썬) (0) | 2022.09.27 |
[삼성sw 1952번] 수영장(파이썬) (1) | 2022.09.24 |
[삼성sw 1949번] 등산로 조정 (1) | 2022.09.23 |
[삼성sw 1767번] 프로세서 연결하기(파이썬) (1) | 2022.09.23 |
댓글 영역