뱀
백준 3190: https://www.acmicpc.net/problem/3190
Edge case
항상 주의해야하는 항목에 대해 정리
1. 방향 설정
- 마지막에 도달했는지 체크
- 변경된 좌표가 있으면 과정이 다 끝난 뒤 x, y = nx, ny 하여 정보 업데이트 필요
2. 행렬
- 인덱스가 1에서 시작하는지 꼭 체크해봐야함
3. 문제 조건
- 뱀이 바로 직전에 있었던 곳이 0이 되는것이 아니라, 꼬리가 있었던 곳이 0이 되어야해
Code
1. 처음 풀이
pypy3 124ms
# 뱀
# 7/25 15:18 ~ 17:05
import sys
input = sys.stdin.readline
n = int(input())
k = int(input())
g = [[0] * n for _ in range(n)]
for i in range(n):
for j in range(n):
g[i][j] = [0, 0]
for _ in range(k): # 사과위치 세팅
x, y = map(int, input().split())
g[x-1][y-1][0] = 2 # 인덱스
l = int(input()) # 방향 전환 횟수 # @@ 꼭 범위 밖인지 체크해줘야해
d = list()
for _ in range(l):
t1, t2 = input().split()
t1 = int(t1)
d.append((t1, t2))
d.append((10000, 'L'))
# 오른쪽 아래 왼쪽 위
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
def is_end(nx, ny): # 벽에 부딪히거나 지 몸이 있거나
if nx < 0 or nx >= n or ny < 0 or ny >= n:
return True
if g[nx][ny][0] == 1:
return True
return False
# 좌표
def solution(x, y):
# 초기 방향 설정
dir = 0
# 초기 시간 설정
t = 0
# 뱀 위치 세팅
g[x][y][0] = 1
# 꼬리 위치 초기화
tx, ty = x, y
# 직진 가즈아
for dt, cd in d: # 몇초뒤, 어떤방향으로 받아오기
for _ in range(dt - t): # 몇초뒤 전까지는 방향유지하면서 직진이지 뭐
nx, ny = x+dx[dir], y+dy[dir]
if is_end(nx, ny):
return t+1
# 프로그램 종료
# 직진 # 사과가 있을땐
if g[nx][ny][0] == 2:
g[nx][ny][0] = 1 # 직진
g[x][y][1] = (nx, ny) # 다음 위치 기록
else: #사과가 없을땐
g[nx][ny][0] = 1
g[x][y][1] = (nx, ny) # 다음 위치 기록하기
g[tx][ty][0] = 0 # 꼬리가 있던 지역 비워주기
tx, ty = g[tx][ty][1] # 꼬리의 좌표 업데이트
# @@@@@@ 이쪽을 관리할 떄 이전이 0되는게 아니고 꼬리의 끝이 0이 되어야해
# 꼬리의 끝 좌표를 계속 저장해놓음녀서 진행해야해
x, y = nx, ny
t += 1 # 이동이 끝나면 시간 추가
# 방향 전환
if cd == 'L': # 왼쪽
dir = (dir - 1) % 4 # @@@ 방향 전환은 언제나 % 써서 방향 전환하기
else: # 오른쪽
dir = (dir + 1) % 4
return t
if __name__ == "__main__":
print(solution(0, 0))
2. 두번째 풀이
pypy3 / 144ms
- Deque를 이용하여 보다 편하게 마지막 꼬리의 좌표 얻기
- 리스트가 간편해지긴하지만, list가 크지않아 속도의 차이없음
from collections import deque
n = int(input())
k = int(input())
g = [[0] * n for _ in range(n)]
for _ in range(k): # 사과위치 세팅
x, y = map(int, input().split())
g[x-1][y-1] = 2 # 인덱스
l = int(input()) # 방향 전환 횟수
d = list()
for _ in range(l):
t1, t2 = input().split()
t1 = int(t1)
d.append((t1, t2))
d.append((10000, 'L'))
# 오른쪽 아래 왼쪽 위
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
def solution(x, y):
q = deque()
dir = 0
t = 0
g[x][y] = 1
deque.append(q, (x, y))
for ct, cd in d:
for _ in range(ct - t):
nx, ny = x+dx[dir], y+dy[dir] # 머리 늘리기
if nx < 0 or nx >= n or ny < 0 or ny >= n or g[nx][ny] == 1:
return t + 1
if g[nx][ny] == 2: # 사과가 있으면
g[nx][ny] = 1
deque.append(q, (nx, ny))
else: # 사과가 없으면
g[nx][ny] = 1 # 머리 내밀고
deque.append(q, (nx, ny))
tx, ty = deque.popleft(q) # 꼬리의 좌표 획득
g[tx][ty] = 0
x, y = nx, ny
t += 1
if cd == 'D':
dir = (dir + 1) % 4
else:
dir = (dir - 1) % 4
return t
if __name__ == "__main__":
print(solution(0, 0))
반응형
'코딩테스트' 카테고리의 다른 글
외벽점검 Python 정리 및 구현 (카카오 기출) (0) | 2022.07.28 |
---|---|
연구소 Python 정리 및 구현 (백준 14502, 삼성 SW 역량테스트 기출) (0) | 2022.07.28 |
치킨 배달 파이썬 정리/구현 (삼성 코테 기출) (0) | 2022.07.26 |
기둥과 보 설치(2020 Kakao) 정리 및 코드 (0) | 2022.07.26 |
[22.07.25] Tistory에 Github Markdown 특성 적용하기 (1) | 2022.07.25 |
댓글