술래잡기

최민수·2023년 7월 19일
0

알고리즘

목록 보기
72/94
# 입력
N, M, H, K = map(int, input().split())
graph = [["-" for _ in range(N)] for _ in range(N)]
runners = []
for i in range(M):
    x, y, d = map(int, input().split())
    # +1 -> default(오른쪽, 아래)
    # -1 -> 왼쪽, 위
    runners.append([x-1, y-1, d, 1])
    graph[x-1][y-1] = "R"
trees = []
for i in range(H):
    x, y = map(int, input().split())
    trees.append([x-1, y-1])
catcher = [N//2, N//2, "T"]
changeDir = []
total = 0
score = 0
while len(changeDir) <= 100:
    for cd in range(1, N):
        for _ in range(2):
            total += cd
            changeDir.append(total)
        if cd == N-1:
            total += cd
            changeDir.append(total)
    for cd in range(N-1, 0, -1):
        for _ in range(2):
            total += cd
            changeDir.append(total)
        if cd == N-1:
            total += cd
            changeDir.append(total)
graph[N//2][N//2] = "C"


def findByPosition(row, col):
    global runners
    itemTemp = []
    for item in runners:
        if item[0] == row and item[1] == col:
            itemTemp.append(item)
    return itemTemp


def graphInit():
    global graph, runners
    graph = [["-" for _ in range(N)] for _ in range(N)]
    for itr in runners:
        r, c = itr[0], itr[1]
        graph[r][c] = "R"


def simulate(turn):
    global runners, catcher, trees, graph, score
    reverse = False
    if (turn//(N*N-1))%2 == 1:
        reverse = True

    # 도망자
    for idx, rn in enumerate(runners):
        if abs(catcher[0]-rn[0]) + abs(catcher[1]-rn[1]) <= 3:
            # 좌우
            if rn[2] == 1:
                nxtX, nxtY = -1, -1
                if rn[3] == 1:
                    nxtX, nxtY = rn[0], rn[1]+1
                elif rn[3] == -1:
                    nxtX, nxtY = rn[0], rn[1]-1
                # 범위 확인
                if 0 <= nxtX < N and 0 <= nxtY < N:
                    if nxtX == catcher[0] and nxtY == catcher[1]:
                        continue
                    if nxtY == N-1 or nxtY == 0:
                        runners[idx] = [nxtX, nxtY, rn[2], (-1)*rn[3]]
                    else:
                        runners[idx] = [nxtX, nxtY, rn[2], rn[3]]
                else:
                    direction = rn[3]*(-1)
                    if direction == 1:
                        if rn[0] == catcher[0] and rn[1]+1 == catcher[1]:
                            runners[idx] = [rn[0], rn[1], rn[2], direction]
                            continue
                        runners[idx] = [rn[0], rn[1]+1, rn[2], direction]
                    elif direction == -1:
                        if rn[0] == catcher[0] and rn[1]-1 == catcher[1]:
                            runners[idx] = [rn[0], rn[1], rn[2], direction]
                            continue
                        runners[idx] = [rn[0], rn[1] - 1, rn[2], direction]
            # 상하
            elif rn[2] == 2:
                nxtX, nxtY = -1, -1
                if rn[3] == 1:
                    nxtX, nxtY = rn[0]+1, rn[1]
                elif rn[3] == -1:
                    nxtX, nxtY = rn[0]-1, rn[1]
                # 범위 확인
                if 0 <= nxtX < N and 0 <= nxtY < N:
                    if nxtX == catcher[0] and nxtY == catcher[1]:
                        continue
                    if nxtX == 0 or nxtX == N-1:
                        runners[idx] = [nxtX, nxtY, rn[2], (-1) * rn[3]]
                    else:
                        runners[idx] = [nxtX, nxtY, rn[2], rn[3]]
                else:
                    direction = rn[3] * (-1)
                    if direction == 1:
                        if rn[0]+1 == catcher[0] and rn[1] == catcher[1]:
                            runners[idx] = [rn[0], rn[1], rn[2], direction]
                            continue
                        runners[idx] = [rn[0]+1, rn[1], rn[2], direction]
                    elif direction == -1:
                        if rn[0]-1 == catcher[0] and rn[1] == catcher[1]:
                            runners[idx] = [rn[0], rn[1], rn[2], direction]
                            continue
                        runners[idx] = [rn[0]-1, rn[1], rn[2], direction]
    # 술래
    catcherDirection = catcher[2]
    if catcherDirection == "T":
        catcher = [catcher[0]-1, catcher[1], catcherDirection]
    elif catcherDirection == "R":
        catcher = [catcher[0], catcher[1]+1, catcherDirection]
    elif catcherDirection == "D":
        catcher = [catcher[0]+1, catcher[1], catcherDirection]
    elif catcherDirection == "L":
        catcher = [catcher[0], catcher[1]-1, catcherDirection]

    if turn in changeDir:
        temp = catcher[2]
        if not reverse:
            if temp == "T":
                catcher[2] = "R"
            elif temp == "R":
                catcher[2] = "D"
            elif temp == "D":
                catcher[2] = "L"
            elif temp == "L":
                catcher[2] = "T"
        else:
            if temp == "T":
                catcher[2] = "L"
            elif temp == "R":
                catcher[2] = "T"
            elif temp == "D":
                catcher[2] = "R"
            elif temp == "L":
                catcher[2] = "D"
    if catcher[0] == 0 and catcher[1] == 0:
        catcher[2] = "D"
    if catcher[0] == N//2 and catcher[1] == N//2:
        catcher[2] = "T"

    # 시야 탐색
    graphInit()
    catcherDirection = catcher[2]
    caught = 0
    if catcherDirection == "T":
        for idx in range(max(0, catcher[0]-2), catcher[0]+1):
            if graph[idx][catcher[1]] == "R":
                if [idx, catcher[1]] in trees:
                    continue
                caughtPerson = findByPosition(idx, catcher[1])
                if caughtPerson:
                    for cp in caughtPerson:
                        caught += 1
                        runners.remove(cp)
    elif catcherDirection == "R":
        for idx in range(catcher[1], min(N, catcher[1]+3)):
            if graph[catcher[0]][idx] == "R":
                if [catcher[0], idx] in trees:
                    continue
                caughtPerson = findByPosition(catcher[0], idx)
                if caughtPerson:
                    for cp in caughtPerson:
                        caught += 1
                        runners.remove(cp)
    elif catcherDirection == "D":
        for idx in range(catcher[0], min(N, catcher[0]+3)):
            if graph[idx][catcher[1]] == "R":
                if [idx, catcher[1]] in trees:
                    continue
                caughtPerson = findByPosition(idx, catcher[1])
                if caughtPerson:
                    for cp in caughtPerson:
                        caught += 1
                        runners.remove(cp)
    elif catcherDirection == "L":
        for idx in range(max(0, catcher[1]-2), catcher[1]+1):
            if graph[catcher[0]][idx] == "R":
                if [catcher[0], idx] in trees:
                    continue
                caughtPerson = findByPosition(catcher[0], idx)
                if caughtPerson:
                    for cp in caughtPerson:
                        caught += 1
                        runners.remove(cp)
    # 점수누적
    score += turn * caught


# 메인 로직
turn = 1
while turn <= K:
    simulate(turn)
    turn += 1

print(score)

2022 삼성 상반기 오전 1번 문제 (G1)

전형적으로 단계별로 나눠서 빡세게 구현시키는 삼성 코테 문제였다.

첫번째 도망자 이동, 두번째 술래 이동, 마지막 시야 체크 후 잡기
이렇게 크게 3가지 단계를 거쳐야 했다.

한가지 찝찝한건, 방향에 따라 조건문 분기가 많아져서 코드가 지저분해졌는데 이 부분을 어떻게 깔끔하게 할 수 있을지다.

방향을 바꾸고, 방향에 따라 이동 시키는 로직에 대한 개선을 생각해봐야 겠다.

그렇게 되면 디버깅 과정도 한참 걸렸는데 조금 더 수월하게 디버깅할 수 있을 것 같다.


출처: https://www.codetree.ai/training-field/frequent-problems/problems/hide-and-seek/description?page=3&pageSize=20

profile
CS, 개발 공부기록 🌱

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

정말 잘 읽었습니다, 고맙습니다!

답글 달기