본문 바로가기

Algorithm & Data Structure

삼성SW 역량 기출 - 싸움땅(2022 하반기 오후 1번)

728x90
반응형

https://www.codetree.ai/training-field/frequent-problems/problems/battle-ground/description?page=1&pageSize=20 

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

n,m,k = map(int,input().split())

player = [] #x위치[0], y위치[1], 방향[2], 초기 능력치[3], 총[4]]

arr = [[[0] for _ in range(n)] for _ in range(n)]

# 하나의 칸에는 여러개의 총이 있을 수 있다.
for i in range(n):
    tmp = list(map(int,input().split()))
    for j in range(n):
        arr[i][j] = [tmp[j]]

#좌표 정규화
for i in range(m):
    p = list(map(int,input().split()))
    p.append(0)
    p[0] -= 1
    p[1] -= 1
    player.append(p)

#졌을때만 이동하는 함수
def r_move(x,y,d):
    if d == 0:  # 위쪽
        if x - 1 < 0:
            nx = x
            nd = 0
        else:
            nx = x - 1
            nd = 0
        ny = y

    elif d == 1:  # 오른쪽
        if y + 1 > n - 1:
            ny = y
            nd = 1
        else:
            ny = y + 1
            nd = 1
        nx = x

    elif d == 2:  # 아래쪽
        if x + 1 > n - 1:
            nx = x
            nd = 2
        else:
            nx = x + 1
            nd = 2
        ny = y

    else:  # 왼쪽
        if y - 1 < 0:
            ny = y
            nd = 3
        else:
            ny = y - 1
            nd = 3
        nx = x

    return nx, ny, nd  # 이동 좌표 반환

#기본 이동 함수
def move(x,y,d):
    if d == 0: #위쪽
        if x-1 < 0:
            nx = x + 1
            nd = 2
        else:
            nx = x - 1
            nd = 0
        ny = y

    elif d == 1: #오른쪽
        if y + 1 > n-1:
            ny = y - 1
            nd = 3
        else:
            ny = y + 1
            nd = 1
        nx = x

    elif d == 2: #아래쪽
        if x + 1 > n-1:
            nx = x - 1
            nd = 0
        else:
            nx = x + 1
            nd = 2
        ny = y

    else: #왼쪽
        if y-1 < 0:
            ny = y + 1
            nd = 1
        else:
            ny = y - 1
            nd = 3
        nx = x

    return nx,ny,nd #이동 좌표 반환

def check_gun(i):
    x = player[i][0]
    y = player[i][1]

    if max(arr[x][y]) > player[i][4]:
        tmp = max(arr[x][y])
        for k in range(len(arr[x][y])):
            if arr[x][y][k] == tmp:
                arr[x][y][k] = player[i][4]
                player[i][4] = tmp

def fight(i,j):
    a = player[i][3] + player[i][4]
    b = player[j][3] + player[j][4]

    if a > b:
        winner = i
    elif b > a:
        winner = j
    elif b == a:
        if player[i][3] > player[j][3]:
            winner = i
        else:
            winner = j

    score = abs(a-b) # 점수 차이

    if winner == i:
        x = player[j][0]
        y = player[j][1]
        d = player[j][2]
        arr[x][y].append(player[j][4])
        player[j][4] = 0

        check_gun(i)

        rx = x #이렇게 rx, ry, rd를 사용하면 이동할 곳이 없을때의 예외처리를 따로 안해줘도 됨
        ry = y
        rd = d

        for _ in range(4):
            nx,ny,nd = r_move(x,y,d%4)
            cnt = 0
            for t in range(m):
                if j != t and player[t][0] == nx and player[t][1] == ny:
                    cnt = cnt + 1
            if cnt == 0:
                rx = nx
                ry = ny
                rd = nd
                break
            d = d + 1
        player[j][0] = rx
        player[j][1] = ry
        player[j][2] = rd
        check_gun(j)

        return [i,score]

    else:
        x = player[i][0]
        y = player[i][1]
        d = player[i][2]
        arr[x][y].append(player[i][4])
        player[i][4] = 0

        check_gun(j)

        rx = x
        ry = y
        rd = d

        for _ in range(4):
            nx,ny,nd = r_move(x,y,d%4)
            cnt = 0
            for t in range(m):
                if i != t and player[t][0] == nx and player[t][1] == ny:
                    cnt = cnt + 1
            if cnt == 0:
                rx = nx
                ry = ny
                rd = nd
                break
            d = d + 1
        player[i][0] = rx
        player[i][1] = ry
        player[i][2] = rd
        check_gun(i)

        return [j,score]

#x위치[0], y위치[1], 방향[2], 초기 능력치[3], 총[4]

answer = [0 for _ in range(m)]

for _ in range(k):
    # m개의 플레이어를 이동
    for i in range(m):
        p_x = player[i][0]
        p_y = player[i][1]
        p_d = player[i][2]
        nx,ny,nd = move(p_x,p_y,p_d)
        player[i][0] = nx
        player[i][1] = ny
        player[i][2] = nd

        ck = 0 # 싸운적이 있는지 확인
        # 싸움 조건이 달성되면 싸움
        for b in range(m):
            if i != b and player[i][0] == player[b][0] and player[i][1] == player[b][1]:
                winner, score = fight(i, b)
                answer[winner] += score
                ck = 1
                break
        #싸운 경험이 없다면 총 바꿀지 확인
        if ck == 0:
            check_gun(i)

#출력
print(*answer)

구현문제는 너무 힘들다..

문제를 꼼꼼하게 잘 읽어야 한다.

 

1. 졌을 때 이동하는 경우와, 그냥 이동하는 경우의 조건이 다르기 때문에 이동 함수를 두 개 만들어야 한다.

2. 한 칸에 총이 여러 개 있을 수 있기 때문에 이를 고려해서 애초에 총의 정보를 리스트로 표현하도록 하자.

3. 좌표가 1,1부터 시작한다.

4. 플레이어 순서대로(순차적으로) 이동하고, 상대를 만나면 싸우고, 아니면 총만 바꿀지 확인한다.

5. 패배한 플레이어는 무조건 무기를 버린다.

 

이러한 부분들을 꼼꼼하게 읽고 코딩을 작성하면서 주석으로 상기시키면서 내가 헷갈리지 않도록 하는 것이 중요한 것 같다. 

 

728x90
반응형