From b6d1a002dde1d7ab3965c719d70347a2ebdefc32 Mon Sep 17 00:00:00 2001 From: IJS1016 Date: Sat, 13 Apr 2024 16:24:39 +0900 Subject: [PATCH] [24.04.2W]python ps, codetree --- ...04\354\235\230\353\260\230\353\236\200.py" | 99 +++++++++++ ...64\354\246\210\353\237\254\353\204\210.py" | 168 ++++++++++++++++++ ...60\354\202\254\353\214\200\352\262\260.py" | 122 +++++++++++++ ...34\355\212\270\353\246\254\353\271\265.py" | 122 +++++++++++++ ...44\353\247\210\354\271\264\354\204\270.py" | 74 ++++++++ 5 files changed, 585 insertions(+) create mode 100644 "\354\240\225\354\204\240/python/codetree/\353\243\250\353\217\214\355\224\204\354\235\230\353\260\230\353\236\200.py" create mode 100644 "\354\240\225\354\204\240/python/codetree/\353\251\224\354\235\264\354\246\210\353\237\254\353\204\210.py" create mode 100644 "\354\240\225\354\204\240/python/codetree/\354\231\225\354\213\244\354\235\230\352\270\260\354\202\254\353\214\200\352\262\260.py" create mode 100644 "\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\353\271\265.py" create mode 100644 "\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\354\230\244\353\247\210\354\271\264\354\204\270.py" diff --git "a/\354\240\225\354\204\240/python/codetree/\353\243\250\353\217\214\355\224\204\354\235\230\353\260\230\353\236\200.py" "b/\354\240\225\354\204\240/python/codetree/\353\243\250\353\217\214\355\224\204\354\235\230\353\260\230\353\236\200.py" new file mode 100644 index 0000000..b1dd7d4 --- /dev/null +++ "b/\354\240\225\354\204\240/python/codetree/\353\243\250\353\217\214\355\224\204\354\235\230\353\260\230\353\236\200.py" @@ -0,0 +1,99 @@ +def get_distance_from_r() : + d_list = [] # [d, r, c, idx] # d min으로 정렬, r max, c max로 정렬하기 위해서! d를 -해주면 정렬이 가능 + for idx, (sr, sc) in enumerate(santas) : + if santa_status[idx] >= 0 : + d = ((sr - rr) ** 2 + (sc - rc) ** 2) + d_list.append([idx, d, sr, sc]) + d_list.sort(key=lambda x:(x[1], -x[2], -x[3])) # d, min으로 정렬 r max, c max 정렬 + return d_list[0] + +def get_distance_from_s(sr, sc) : # td이 d보다 작아서 가까워질때만 d_list에 넣어줌, idx는 direction 우선순위 + direction = [[-1, 0], [0, 1], [1, 0], [0, -1]] # 상우하좌 + d_list = [] + d = ((sr - rr) ** 2 + (sc - rc) ** 2) # 기존 거리보다 작아야됨 + for idx, (dr, dc) in enumerate(direction) : + td = ((sr + dr - rr) ** 2 + (sc + dc - rc) ** 2) + if d > td : + d_list.append([idx, td, dr, dc]) + d_list.sort(key=lambda x:(x[1], x[0])) + return d_list + +def push_santa(tsr, tsc, mr, mc, sidx) : # 산타가 이동하는 좌표 tsr, tsc 받아서, push 해줌 + if 1 <= tsr <= N and 1 <= tsc <= N: # 범위내 있으면 산타 index 변경, 기절 상태로 변경 + for siidx, santa in enumerate(santas): # 산타 위치 돌면서 자리에 산타 있는지 확인 + if [tsr, tsc] == santa and sidx != siidx: # 산타 겹치는 경우 + santas[sidx] = [tsr, tsc] # 기존 산타를 이동 + push_santa(tsr+mr, tsc+mc, mr, mc, siidx) # 이동할 산타 옮기기 + break + santas[sidx] = [tsr, tsc] + else : # 탈락 라운드 작성(나중에 점수에 +하면 됨), 근데 기절상태라면,,? <0일때만 +로 바꿔주는 함수 넣기 + santas[sidx] = [-N, -N] # 존재하지 않는 위치로 변경, distance 가장 높게 나오기 위해서 -N? + santa_status[sidx] = -m +# 입력 ########################################################### +N, M, P, C, D = map(int, input().split(" ")) +rr, rc = map(int, input().split(" ")) + +santas = [] +santa_status = [0] * P # -(퇴장라운드), 0, +(기절) 퇴장, 정상, 기절 +santa_score = [0] * P # score + +for _ in range(P) : + santas.append(list(map(int, input().split(" ")))) +santas.sort(key = lambda x : x[0]) +santas = [s[1:] for s in santas] # santas [sr, sc]이고 1번부터 P까지 순서대로 있음 +###################################################################### + +for m in range(1, M+1) : # 1번-M번 턴, 남은 산타에 대해서만 +1점 + # 기절 산타들 풀어주기 + for i in range(P) : + if santa_status[i] > 0 : + santa_status[i] -= 1 + # 루돌프 이동, 산타와 가까워지는 방향으로 + sidx, dx, sr, sc = get_distance_from_r() # d_list에서 산타 존재하면, 충돌! + dr = (sr - rr) / abs(sr - rr) if rr - sr != 0 else 0 + dc = (sc - rc) / abs(sc - rc) if rc - sc != 0 else 0 + rr = rr + dr + rc = rc + dc + # 충돌 발생 + if [rr, rc] in santas : + santa_score[sidx] += C + tsr, tsc = santas[sidx][0] + dr * C, santas[sidx][1] + dc * C # 루돌프 이동 방향으로 C칸 물러남 + if 1 <= tsr <= N and 1 <= tsc <= N : # 범위내 있으면 산타 index 변경, 기절 상태로 변경 + santa_status[sidx] = 2 + push_santa(tsr, tsc, dr, dc, sidx) + else : # 탈락 라운드 작성(나중에 점수에 +하면 됨), 근데 기절상태라면,,? <0일때만 +로 바꿔주는 함수 넣기 + santas[sidx] = [-N, -N] # 존재하지 않는 위치로 변경 + santa_status[sidx] = -m + + # 산타 거리 계산 후 이동 ###########################3 + # 산타 거리 계산할 때...상우하좌 + for sidx in range(P): + if santa_status[sidx] == 0: # 정상일 때만 이동 + sr, sc = santas[sidx] + condi_list = get_distance_from_s(sr, sc) + mr, mc = 0, 0 + for condi in condi_list : + _, _, dr, dc = condi + if [sr+dr, sc+dc] not in santas : + mr, mc = dr, dc # 이동 확정 + break + # 산타 이동 + sr, sc = sr + mr, sc + mc + if [sr, sc] == [rr, rc] : # 루돌프와 충돌 발생 확인, 루돌프는 반드시 map 범위 안에 있으니 추가 검사 필요하지 않음 + santa_score[sidx] += D + tsr, tsc = sr + mr * (-D), sc + mc * (-D) + santa_status[sidx] = 2 # 기절 + push_santa(tsr, tsc, -mr, -mc, sidx) + else : + santas[sidx] = [sr, sc] + + if max(santa_status) < 0 : + break + +# 출력 ############################################# +for sidx in range(P) : + if santa_status[sidx] < 0 : # 탈락 산타만 탈락 라운드 점수 더해주기 + santa_score[sidx] -= (santa_status[sidx]+1) + else : + santa_score[sidx] += M # 탈락하지 않은 산타는 M 라운드 더해주고 + print(santa_score[sidx], end=" ") \ No newline at end of file diff --git "a/\354\240\225\354\204\240/python/codetree/\353\251\224\354\235\264\354\246\210\353\237\254\353\204\210.py" "b/\354\240\225\354\204\240/python/codetree/\353\251\224\354\235\264\354\246\210\353\237\254\353\204\210.py" new file mode 100644 index 0000000..c4c0ed9 --- /dev/null +++ "b/\354\240\225\354\204\240/python/codetree/\353\251\224\354\235\264\354\246\210\353\237\254\353\204\210.py" @@ -0,0 +1,168 @@ +# 입력) +# N, M, K +# NxN 미로 정보) 0, (1-9) 벽 +# M 참가자 좌표) 초기에는 빈칸에만 존재 +# 출구 좌표 -> 빈칸... + +# 출력) 모든 참가자들의 이동 거리 합과 출구 좌표를 출력 +class Point : + def __init__(self, r, c): + self.r = r-1 + self.c = c-1 + +# 입력 받으면서 -1해서 범위 (0, N-1)로 변경 +# 입력 받기 ################################################ +N, M, K = map(int, input().split(" ")) +mmap = [] +persons = [] +person_status = [True] * M +total_move = 0 +for _ in range(N) : + mmap.append(list(map(int, input().split(" ")))) +for _ in range(M) : + r, c = map(int, input().split(" ")) + persons.append(Point(r, c)) +r, c = map(int, input().split(" ")) +exit_p = Point(r, c) +####################################################### +def get_distance(r, c) : + return(abs(exit_p.r-r)+abs(exit_p.c-c)) + +def check_out_mmap(r, c) : + if (0 <= r < N) and (0 <= c < N) : + return True + return False + +def persons_move() : + # 모든 참가자 이동 - 벽 없는 곳, 가까워지는 곳, 우선순위 상하, 중첩 가능, 이동 횟수 +1, 출구 이동 시 탈출 + global total_move + directions = [[-1, 0], [1, 0], [0, -1], [0, 1]] # 우선순위 상하 + for i, p in enumerate(persons) : + if person_status[i] : + od = get_distance(p.r, p.c) # 이동 전 distance 계산, original_distance : od + for drt in directions : + dr, dc = drt + nr, nc = p.r + dr, p.c + dc + if check_out_mmap(nr, nc) and mmap[nr][nc] == 0: # 맵을 나가지 않고, 벽이 없으면 + if od > get_distance(nr, nc) : # 새롭게 얻은 거리가 더 작으면 + persons[i].r, persons[i].c = nr, nc # 사람 이동 + total_move += 1 + break # DBG) 새롭게 얻은 거리가 더 작으면? 무조건 1차이 아님? 틀리면 break 빼기 + if [persons[i].r, persons[i].c] == [exit_p.r, exit_p.c] : # 출구 이동 시 탈출, REVIEW : class 비교 꺼내서 해야됨 바로 X + person_status[i] = False + +# 정사각형을 어떻게 잡을지 +# 같은 사람을 포함하는 정사각형이 어려개 있을 수 있음 +# 크기 먼저..., r,c 범위 +# DBG) 맵 범위? 상관 있음 - 사람이 오른쪽 하단에? 상관 없나..? 우선 해보고 틀리면 생각 +# mmap slicing할 떄 범위 [min_r, max_r+1] 주의 +def search_rectangle() : + er, ec = exit_p.r, exit_p.c + rectangles = [] # [l, r, c]로 저장 + dlist = [] + for i, p in enumerate(persons) : + if person_status[i] : + dr, dc = p.r - er, p.c - ec # P - E + l = max([abs(dr), abs(dc)]) # 정사각형 길이(3이면 2가 저장됨에 유의) + # p에서 좌상단 할 수 있는 케이스 4개 확인 + # [0, 0], [0, l], [l, 0], [0, -l], [-l, 0], # REVIEW : 범위 제대로 + for dlr in range(-l, l+1) : + for dlc in range(-l, l+1) : + # dlr, dlc = dl # 좌상단 좌표 찾기 위해서... + tr, tc = er + dlr, ec + dlc # 출구 기준 좌상단 tr, tc + if check_out_mmap(tr, tc) and tr <= p.r <= tr + l and tc <= p.c <= tc + l : # 범위 내 사람이 있으면 + rectangles.append([l, tr, tc]) + tr, tc = p.r + dlr, p.c + dlc # 사람 기준 좌상단 tr, tc + if check_out_mmap(tr, tc) and tr <= er <= tr + l and tc <= ec <= tc + l: # 범위 내 사람이 있으면 + rectangles.append([l, tr, tc]) + # 최종 sort + rectangles.sort(key=lambda x : (x[0], x[1], x[2])) # 길이 작은 순, r, c 좌표 작은 우선순위 + return rectangles[0] + +def check_inside_rect(rr, rc, rl, r, c) : + if rr <= r <= rr + rl and rc <= c <= rc + rl: + return True + return False +def rotate_rectangle(rl, rr, rc) : + rotated_infos = [] # 회전된 r, c, value 순으로 저장 + # 맵 회전 정보 저장 + for tr, line in enumerate(mmap) : + for tc, v in enumerate(line) : + if check_inside_rect(rr, rc, rl, tr, tc) : + # if rr <= tr <= rr + rl and rc <= tc <= rc + rl : + rotated_infos.append([tc - rc + rr, rl - (tr - rr) + rc, max(v-1, 0)]) # shift + if DBG : + print(f"ROTATED ({rr}, {rc}), size {rl}") + # print("rotated_infos") + # for ri in rotated_infos : + # print(ri) + # 저장된 회전 정보 맵에 써주기 + for info in rotated_infos : + r, c, v = info + mmap[r][c] = v + # exit, person 회전 + for i, p in enumerate(persons) : + if person_status[i] : + if check_inside_rect(rr, rc, rl, p.r, p.c) : + persons[i].r, persons[i].c = p.c - rc + rr, rl - (p.r - rr) + rc # DBG) person[i]말고 p.c = 없는지, 이렇게 해도 되는지 확인하기 + exit_p.r, exit_p.c = exit_p.c - rc + rr, rl - (exit_p.r - rr) + rc + + +def print_mmap() : + print(" ", end="") + for i in range(N) : + print(change_color_y(f" {i}"), end="") + print() + for i, m in enumerate(mmap) : + print(change_color_y(f"{i} "), end="") + ptr_str = '' + for j, mm in enumerate(m) : + flag = True + if [exit_p.r, exit_p.c] == [i, j] : + ptr_str += change_color_b(f"{mm}") + " " + flag = False + for pi, p in enumerate(persons): + if person_status[pi]: + if [p.r, p.c] == [i, j] : + ptr_str += change_bg(f"{mm}") + " " + flag = False + break + if flag : + ptr_str += f"{mm} " + print(ptr_str) + +def change_color_y(s) : + return '\033[31m' + str(s) + '\033[0m' +def change_color_b(s) : + return '\033[34m' + str(s) + '\033[0m' +def change_bg(s) : + return '\033[43m' + str(s) + '\033[0m' + +bm = 0 +DBG = False +for k in range(K) : # K번 실행 + if DBG : + print(f"\n\n!! {k+1}초") + print("before rot") + print_mmap() + persons_move() + if DBG : + print(f"people move {total_move-bm}") + print_mmap() + + if not max(person_status) : + if DBG : print("NO PP") + break + + # 회전할 정사각형 서치 - 사람 한 명이라도 포함해야함, 크기 작은 순, 좌상단 r, c 작은 순 우선 + rl, rr, rc = search_rectangle() # rectangle, 이때 길이 3이면 rl에는 2가 저장 + # 정사각형 회전 - 출구, 포함된 사람, 벽 모두 회전 => 시계 방향 회전 + rotate_rectangle(rl, rr, rc) # 시계 방향 회전을 어떻게 구현(C, N-R) + if DBG: + bm = total_move + print(f"{k+1} after rot") + print_mmap() + # 사람들 없으면 break + +print(total_move) +print(exit_p.r+1, exit_p.c+1) \ No newline at end of file diff --git "a/\354\240\225\354\204\240/python/codetree/\354\231\225\354\213\244\354\235\230\352\270\260\354\202\254\353\214\200\352\262\260.py" "b/\354\240\225\354\204\240/python/codetree/\354\231\225\354\213\244\354\235\230\352\270\260\354\202\254\353\214\200\352\262\260.py" new file mode 100644 index 0000000..5fbfbab --- /dev/null +++ "b/\354\240\225\354\204\240/python/codetree/\354\231\225\354\213\244\354\235\230\352\270\260\354\202\254\353\214\200\352\262\260.py" @@ -0,0 +1,122 @@ +# 입력 +# L N Q # L : 체스판 크기, N : 기사 수, Q : 명령 +# L개 줄에 겹쳐 LxL 체스판 정보, 0 : 빈칸, 1 : 함정, 2: 벽 +# N명 기사 정보(순서대로) : r, c, h, w, k - 위치 (r, c), 방패 (h, w) 체력 k +# Q개 명령 : i, d i번째 기사 d로 한칸 이동(사라진 기사 번호가 주어질 수 있음) +# d (0, 1, 2, 3) : 상 우 하 좌 +# 처음에는 기사들끼리 겹쳐지지 않고, 기사와 벽은 겹쳐서 주어지지 않음 + +# 출력 +# Q 명령 후 생존 기사들의 받은 총 데미지 합 + +DBG = False +class Knight : + def __init__(self, r, c, h, w, k): + self.r = r + self.c = c + self.h = h # 방패 바로 더해주려고 -1 해줌, 인덱싱할 땐 그냥 써야되네;... + self.w = w + self.k = k + self.d = 0 + self.status = True + def get_infos(self): + return [self.r, self.c, self.h, self.w] + +# 입력 ################################################ +L, N, Q = map(int, input().split(" ")) +mmap = [] +knights = [] +orders = [] +total_damage = [0] * N +for _ in range(L) : + mmap.append(list(map(int, input().split(" ")))) +for _ in range(N) : + r, c, h, w, k = map(int, input().split(" ")) + knights.append(Knight(r, c, h, w, k)) +for _ in range(Q) : + orders.append(map(int, input().split(" "))) +###################################################### + +def check_mapout(r, c, h, w) : + if 1 <= r <= L and 1 <= c <= L and 1 <= r+h-1 <= L and 1 <= c+w-1 <= L : + return True + return False +def check_overlap(tr, tc, h, w, other_knight) : + ot_r, ot_c, ot_h, ot_w = other_knight.get_infos() + # 잘못!! 어떤게 더 클지 모르니까 둘다 해줘야되네... + if (tr <= ot_r <= tr+h-1) or (tr <= ot_r+ot_h-1 <= tr+h-1) : # 세로 방향 겹치는지 + if (tc <= ot_c <= tc+w-1) or (tc <= ot_c+ot_w-1 <= tc+w-1): # 가로 방향 겹치는지 + return True + if (ot_r <= tr <= ot_r+ot_h-1) or (ot_r <= tr+h-1 <= ot_r+ot_h-1): # 세로 방향 겹치는지 + if (ot_c <= tc <= ot_c+ot_w-1) or (ot_c <= tc+w-1 <= ot_c+ot_w-1): # 가로 방향 겹치는지 + return True + + return False + +def get_max_value(tr, tc, h, w) : + max_value = 0 + for m in mmap[tr - 1:tr + h - 1] : # tr이 1부터 시작하니까 + tmp = max(m[tc - 1:tc + w - 1]) + if max_value < tmp : + max_value = tmp + return max_value + +def get_damage(r, c, h, w) : + damage = 0 + for m in mmap[r - 1:r + h - 1] : + for v in m[c - 1:c + w - 1] : + if v == 1 : damage+=1 + return damage + +# 뭐가 하나라도 안되면 False로 return해서 돌지 않도록 +# 최종으로 된다고 하면 True랑 history return해서 위치 바꿔주면서 패널티 세기 +def push_knights(knight, kidx, move, history): + # 이동 시 밀 수 있는지 검사 + mr, mc = move + tr, tc = knight.r+mr, knight.c+mc + h, w = knight.h, knight.w + if not check_mapout(tr, tc, h, w) : # 맵 범위 밖이거나 + if DBG :print(f"NO! knight {kidx+1} - map out") + return False, history # 이동 불가 + elif get_max_value(tr, tc, h, w) == 2 : # 벽이 있으면 + if DBG : print(f"NO! knight {kidx+1} - wall") + return False, history + # 이동 불가 + else : # 벽이 없다면 이동 가능 + if DBG :print(f"GO! knight {kidx+1}") + history[kidx] = [tr, tc] # new tr, tc + for idx, other_knight in enumerate(knights): # 기사가 있는지 검사 + if other_knight.status : # 기사가 살아있을 때 + if idx != kidx and idx not in history.keys(): # 자기 자신이 아니고 다른 기사랑 만났을 때, 본 것들이 아닐 때 + if DBG : print(f"-> check knight {idx+1}") + if check_overlap(tr, tc, h, w, other_knight) : # 겹치는 영역이 있으면 + if DBG: print(f"overlap knight {idx + 1} info {other_knight.r, other_knight.c, other_knight.h, other_knight.w}") + flag, history = push_knights(other_knight, idx, [mr, mc], history) # 다시 밀어내기 + if not flag : + return False, None + return True, history + +direct = ['상', '우', '하', '좌'] +directions = [[-1, 0], [0, 1], [1, 0], [0, -1]] # 상우하좌 +for (kidx, d) in orders : + kidx -= 1 + if DBG : print(f"!!! Order Knight : {kidx+1}, {direct[d]}") + if knights[kidx].status : # 기사가 살아있으면 + flag, history = push_knights(knights[kidx], kidx, directions[d], {}) + if DBG : print(flag, history) + if flag : + for hkidx, (nr, nc) in history.items() : # 좌표 업데이트, 업데이트 하면서 패널티도 받게 하기 + knights[hkidx].r, knights[hkidx].c = nr, nc # 좌표값 업데이트 + if hkidx != kidx: # 명령 아닌거만 패널티 + h, w = knights[hkidx].h, knights[hkidx].w # 쉽게 쓸라고, 노의미 + knights[hkidx].d += get_damage(nr, nc, h, w) + if knights[hkidx].k <= knights[hkidx].d : + knights[hkidx].status = False + +result = 0 +for kidx, knight in enumerate(knights) : + if knight.status : + if DBG : print(f"{kidx+1}D : {knight.d}") + result += knight.d + +print(result) diff --git "a/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\353\271\265.py" "b/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\353\271\265.py" new file mode 100644 index 0000000..5347fb1 --- /dev/null +++ "b/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\353\271\265.py" @@ -0,0 +1,122 @@ +from collections import deque +# 입력 +N, M = map(int, input().split(" ")) +basecamps = [] +mmap_status = [[True] * N for _ in range(N)] # REVIEW : [[True] * N] * N으로 쓰면 soft copy되서 한 값 바뀌면 나머지도 다 같이 바뀌는거 주의 +mmap_length = [[0] * N for _ in range(N)] +store = [] +person_status = [-1] * M # -1 : 대기중, 0 : 이동중, 1 : 도착 +persons = [[-1, -1] for _ in range(M)] # -1, -1 좌표로 모두 초기화, REVIEW : 마찬가지로 class list의 * N도 안됨.. + +for i in range(N) : + tmp = list(map(int, input().split())) + for j, v in enumerate(tmp) : + if v == 1 : + basecamps.append([i, j]) # 베이스캠프 좌표 저장 +for i in range(M): + ll = input().split() + # print(i, ll) + store.append(list(map(int, ll))) +for i, s in enumerate(store) : + for j, ss in enumerate(s) : + store[i][j] -= 1 + +def check_inside_map(y, x) : + if 0<=y 이걸 맵으로 바꾸면 됨...좀만 쉬고 바꾸고 해설하고 도서관 가자.. +visited = [[[False] for _ in range(N)] for _ in range(N)] +step = [[[0] for _ in range(N)] for _ in range(N)] +directions = [[-1, 0], [0, -1], [0, 1], [1, 0]] # 상좌우하 우선순위 +def get_shortest_routes(p1, p2, cutoff=N*N) : + y1, x1 = p1 # 시작 위치 + y2, x2 = p2 # 도착 목표 + # visited, step 값을 전부 초기화합니다. + for i in range(N): + for j in range(N): + visited[i][j] = False + step[i][j] = 0 + routes = deque([[y1, x1]]) + visited[y1][x1] = True + + # 돌면서 get_shortest 다시 실행하면서 list에 추가하기, 근데 끝까지 가자나 dfs하면...bfs로 해야좋은거아냐? -> 리스트 뒤에 넣고 계속 뽑으면서 해주기 + while len(routes) > 0 : + tmp_routes = routes.popleft() # 맨 앞에 루트 pop + ny, nx = tmp_routes + step_n = step[ny][nx] + if step_n > cutoff: # 원하는 것보다 크면 return 해주기 + return cutoff+1 + for (dy, dx) in directions : # 상좌우하 우선순위대로 방문 + ty, tx = ny + dy, nx + dx + if check_inside_map(ty, tx) : + if not visited[ty][tx] and mmap_status[ty][tx]: # 지금까지 방문한 위치 제외 + visited[ty][tx] = True + step[ty][tx] = step_n + 1 + routes.append([ty, tx]) + if [ty, tx] == [y2, x2]: # 도착한다면! + return step_n + 1 + return N*N +def b_p(s) : return f"\033[045m{s}" +def b_r(s) : return f"\033[041m{s}" +def print_mmap(mmap, p, s): # 사람 위치 color로 지정, basecamp 위치 bc, 이동 불가능 영역 br + for i, m in enumerate(mmap) : + for j, mm in enumerate(m) : + tmp = mm + if [i, j] == p: + tmp = b_p(tmp) + if [i, j] == s : + tmp = b_r(tmp) + print(f"{tmp}\033[0m ", end="") + print() + print() +# 시간초과) 길 계속 계산 안해주기 위해서 routes 저장하고 그 의외의 것들 제외해주기 +t = 0 +# before_route = {i:[] for i in range(M)} +while min(person_status) < 1 : # 모두 다 도착하면 while stop + # print(person_status) + mmap_update = [] # False로 설정할 좌표들 + for i, p in enumerate(persons) : + sy, sx = store[i][0], store[i][1] # 의미 없음 편하게 쓰려고, store + if person_status[i] == 0 : + get_shortest_routes(store[i], p) # 최단거리 구해서 1칸 이동 + tmp_list = [] + for di, (dy, dx) in enumerate(directions) : + ty, tx = p[0] + dy, p[1] + dx + if check_inside_map(ty, tx) and visited[ty][tx] : + tmp_list.append([di, step[ty][tx], ty, tx]) + tmp_list.sort(key=lambda x :(x[1], x[0])) + persons[i] = tmp_list[0][2:] # 1칸 이동, route에서 시작 지점말고 다른데로 + if persons[i] == [sy, sx] : # 편의점 도착 시, mmap 이동 X으로 설정(그 이후에 이동 X), 사람 status False로 설정 + mmap_update.append([sy, sx]) + person_status[i] = 1 # 사람 도착! + + # LATER) 사람들 이동 완료 후, mmap_status 값들 False로 변경 + for (y, x) in mmap_update : + mmap_status[y][x] = False + + # 3번 작동 + if t < len(store) : # t가 사람 총 개수보다 커지면 X, store 사람의 목표 편의점 + min_l = N*N + tmp_route = [] + for i, bc in enumerate(basecamps) : # 베이스캠프와 편의점 사이 최단 거리 계산 + l = get_shortest_routes(bc, store[t], min_l) + if min_l > l : + min_l = l + tmp_route = [[bc[0], bc[1], i]] + elif min_l == l : + tmp_route.append([bc[0], bc[1], i]) # 중복된거 나중에 정렬해주려고 + tmp_route.sort(key=lambda x:(x[0], x[1])) # 행, 렬 우선순위대로 정렬 + b_idx = tmp_route[0][-1] # bc 정해짐 + by, bx = basecamps[b_idx] + mmap_status[by][bx] = False # mmap 이동 X으로 설정, + basecamps.pop(b_idx) # 베이스캠프 삭제 + + person_status[t] = 0 # 사람 이동 상태 + persons[t] = [by, bx] # 사람 위치 베이스캠프로 이동 + + t += 1 + +print(t) \ No newline at end of file diff --git "a/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\354\230\244\353\247\210\354\271\264\354\204\270.py" "b/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\354\230\244\353\247\210\354\271\264\354\204\270.py" new file mode 100644 index 0000000..d37a6bd --- /dev/null +++ "b/\354\240\225\354\204\240/python/codetree/\354\275\224\353\223\234\355\212\270\353\246\254\354\230\244\353\247\210\354\271\264\354\204\270.py" @@ -0,0 +1,74 @@ +L, Q = map(int, input().split(" ")) # 초밥 길이, 명령 수 +sushis = {} +customers = {} +queries = [] +names = [] + +class Query : + def __init__ (self, cmd, t, x, name, n) : + self.cmd = cmd + self.t = t + self.x = x + self.name = name + self.n = n + +for _ in range(Q) : + t, x, name, n = -1, -1, -1, -1 + cmd, *infos = input().split(" ") + cmd = int(cmd) + if cmd == 100 : + t, x, name = infos + t, x = map(int, [t, x]) + elif cmd == 200 : + t, x, name, n = infos + t, x, n = map(int, [t, x, n]) + else : + t = int(infos[0]) + + queries.append(Query(cmd, t, x, name, n)) + + if cmd == 100 : + if name not in sushis: + sushis[name] = [queries[-1]] + else: + sushis[name].append(queries[-1]) + elif cmd == 200 : + customers[name] = queries[-1] + +# 초밥 제거 command 110, 사람 제거 210 +for name in sushis.keys() : # name + customer = customers[name] + + time = 0 + last_time = 0 + sushis[name].sort(key=lambda x : x.t) + for sushi in sushis[name] : + if sushi.t < customer.t : # 초밥이 더 빨리 들어온 경우 + sushi_x = (customer.t - sushi.t + sushi.x) % L + time = customer.t + else : # 초밥이 더 늦게 들어온 경우 + sushi_x = sushi.x + time = sushi.t + + time = time + (L + customer.x - sushi_x) % L + last_time = max(time, last_time) + + queries.append(Query(110, time, -1, -1, -1)) # 초밥 out + # queries.append(Query(220, time, -1, -1, -1)) # 사람 out + queries.append(Query(220, last_time, -1, -1, -1)) # 사람 out + +queries.sort(key=lambda q: (q.t, q.cmd)) + +people_num, sushi_num = 0, 0 +for i in range(len(queries)): + # print(queries[i].cmd, queries[i].t) + if queries[i].cmd == 100: # 초밥 추가 + sushi_num += 1 + elif queries[i].cmd == 110: # 초밥 제거 + sushi_num -= 1 + elif queries[i].cmd == 200: # 사람 추가 + people_num += 1 + elif queries[i].cmd == 220: # 사람 제거 + people_num -= 1 + else: # 사진 촬영시 답을 출력하면 됩니다. + print(people_num, sushi_num)