Super Kawaii Cute Cat Kaoani [삼성 SW 역량 테스트 기출, Python] 싸움땅 풀이

기타/코테 대비

[삼성 SW 역량 테스트 기출, Python] 싸움땅 풀이

치킨고양이짱아 2025. 4. 12. 22:07
728x90
728x90

2022 하반기 오전 1번 문제인 '싸움땅' 문제 풀이입니다.

 

1. 문제 링크

https://www.codetree.ai/ko/frequent-problems/problems/battle-ground/description

 

삼성 코딩테스트 기출 문제 설명: 싸움땅 | 코드트리

삼성전자 코딩테스트 기출 문제 싸움땅의 상세 설명입니다. 문제 요구사항을 정확히 파악하고 효율적인 알고리즘을 설계해보세요.

www.codetree.ai

 

2. 한줄평

bfs, dfs 없는 노가다 시뮬레이션 문제! 확실히 최근 기출이 훨씬 어려운것 같다..3년전만 해도 훨씬 낫네🥲

 

3. 코드

N, M, K = map(int, input().split())
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

board = []
for i in range(N):
    row_list = []
    for j in range(N):
        row_list.append([])
    board.append(row_list)

for i in range(N):
    info = list(map(int, input().split()))
    for j in range(len(info)):
        if info[j] != 0:
            board[i][j].append(info[j])

current_player_list = []
for i in range(M):
    x, y, d, s = map(int, input().split())
    x = x-1
    y = y-1
    current_player_list.append(((x, y), d, s, 0))

def get_inverse_direction(d):
    return (d+2)%4

def get_first_new_pos(pos, d):
    '''
    current_palyer_lit update하지 않음
    그 칸에 뭐있는지 상관없이 update 했을 때 새로운 pos와 direction return
    '''
    cur_x, cur_y = pos
    new_x, new_y = cur_x+dx[d], cur_y+dy[d]

    if 0<=new_x<N and 0<=new_y<N: # 격자 안에 있을 경우
        return (new_x, new_y), d
    else:
        new_d = get_inverse_direction(d)
        new_x, new_y = cur_x+dx[new_d], cur_y+dy[new_d]
        return (new_x, new_y), new_d

def fight(p_index1, p_index2):
    '''
    이긴 사람 얻는 포인트, 이긴 사람 인덱스, 진 사람 인덱스 순으로 Return
    '''
    p1_info = current_player_list[p_index1]
    p1_power = p1_info[2]+ p1_info[3]

    p2_info = current_player_list[p_index2]
    p2_power = p2_info[2] + p2_info[3]


    if p1_power > p2_power:
        winner_index = p_index1
        los_index = p_index2
    elif p1_power < p2_power:
        winner_index = p_index2
        los_index = p_index1
    else: # 같을 경우
        if p1_info[2] > p2_info[2]:
            winner_index = p_index1
            los_index = p_index2
        else:
            winner_index = p_index2
            los_index = p_index1
    winner_point = abs(p1_power - p2_power)

    return winner_point, winner_index, los_index

def get_gun(p_index):
    '''
    update된 현 위치에서 총 얻기
    '''
    cur_pos, d, init, gun = current_player_list[p_index]
    board_gun_list = board[cur_pos[0]][cur_pos[1]][:]

    if gun > 0:
        board_gun_list.append(gun)

    max_gun_index = -1
    max_gun_power = -1
    for i in range(len(board_gun_list)):
        if board_gun_list[i] > max_gun_power:
            max_gun_power = board_gun_list[i]
            max_gun_index = i

    if max_gun_index == -1: # 나도 총 없고 board에도 없는 경우
        return
    else:
        my_gun_power = max_gun_power
        board_gun_list.pop(max_gun_index)
        board[cur_pos[0]][cur_pos[1]] = board_gun_list
        current_player_list[p_index] = (cur_pos, d, init, my_gun_power)

def put_gun(p_index):
    '''
    내가 가지고 있는 gun 현위치에 놔두기 board와 people_po
    '''
    cur_pos, d, init, gun = current_player_list[p_index]
    if gun > 0:
        board[cur_pos[0]][cur_pos[1]].append(gun)
        current_player_list[p_index] = (cur_pos, d, init, 0)
    return

def get_lose_new_pos(p_index):
    '''
    current_palyer_lit update하지 않음
    새로운 pos와 direction return

    자기가 왔던 자리가 있으니 무조건 움직일순 있음
    '''
    cur_pos, d, init, gun = current_player_list[p_index]
    for i in range(4):
        current_d = (d+i)%4
        new_x, new_y = cur_pos[0]+dx[current_d], cur_pos[1]+dy[current_d]
        is_possible = True
        if 0<=new_x<N and 0<=new_y<N:
            for an_p_index in range(len(current_player_list)):
                if p_index != an_p_index:
                    another_pos = current_player_list[an_p_index][0]
                    if (new_x, new_y) == another_pos:
                        is_possible = False
                        break
        else:
            is_possible = False

        if is_possible:
            return (new_x, new_y), current_d

def one_people_simulation(p_index):
    global one_round_point_list

    cur_pos, d, init_power, gun = current_player_list[p_index]

    new_pos, new_d = get_first_new_pos(cur_pos, d)

    current_player_list[p_index] = (new_pos, new_d, init_power, gun)


    for an_p_index in range(len(current_player_list)):
        if an_p_index != p_index and current_player_list[an_p_index][0] == new_pos:
            # 싸우는 경우
            point, winner_index, loser_index = fight(p_index, an_p_index)
            one_round_point_list[winner_index] += point

            # 진 친구는 총 놓기
            put_gun(loser_index)
            new_loser_pos, new_loser_dir = get_lose_new_pos(loser_index)

            current_player_list[loser_index] = (new_loser_pos, new_loser_dir, current_player_list[loser_index][2], current_player_list[loser_index][3])

            get_gun(loser_index)
            # 이긴 친구는 가지기
            get_gun(winner_index)
            return

    get_gun(p_index)

one_round_point_list = [0] * M
def one_round():
    for p_index in range(M):
        one_people_simulation(p_index)


for i in range(K):
    one_round()
print(*one_round_point_list)
728x90
728x90