[Samsung] 2022-2 오전 1번 싸움땅

Question

Language: Python

Difficulty: Gold 2

해당 문제는 주어진 문제의 조건에 따라 시뮬레이션을 구현하면 되는 문제이다.

시뮬레이션 과정은 아래와 같다.

  1. 플레이어의 이동 2-1. 이동한 자리에 플레이어가 있는 경우 싸운다. 2-1-2. 진 플레이어의 이동 2-1-2. 이긴 플레이어의 처리 2-2. 이동한 자리에 플레이어는 없고, 총이 있는 경우
  1. 플레이어의 이동

본인의 방향대로 다음 한 칸으로 이동하고, 만약 경계을 넘어서는 경우 정반대 방향으로 1칸 이동한다.

row,col,dir,start_attack,gun_info=players[current_player]
#현재 공격력
attack_point=start_attack+gun_info
next_row=row+dy[dir]
next_col=col+dx[dir]

#범위를 넘어서는 경우 방향을 반대로 해서 한 칸 간다.
if next_row < 0 or next_row >=n or next_col < 0 or next_col >=n:
    next_dir=(dir+2)%4
    players[current_player][2]=next_dir
    next_row=row+dy[next_dir]
    next_col=col+dx[next_dir]

#현재 플레이어를 이동시킨다.
players[current_player][0]=next_row
players[current_player][1]=next_col
player_map[row][col]=-1

2-1: 이동한 칸에 다른 플레이어가 있으면 싸운다.

이때, 플레이어의 공격력 + 총의 합산을 비교해서 더 높은 쪽이 승자가 되며, 만약 동일한 경우 플레이어의 공격력을 비교한다.

#해당 자리에 플레이어가 있는 경우
opposite_player=player_map[next_row][next_col]
if opposite_player!=-1:
    opposite_row,opposite_col,opposite_dir,opposite_start_attack,opposite_gun_info=players[opposite_player]

    #상대방의 공격력
    opposite_attack_point=opposite_start_attack+opposite_gun_info
    winner,loser=-1,-1
    #상대방의 공격력이 더 높은 경우
    if attack_point < opposite_attack_point:
        winner,loser=opposite_player,current_player
    
    #공격력이 서로 같은 경우, 플레이어의 초기 공격력을 비교한다.
    elif attack_point == opposite_attack_point:
        if start_attack < opposite_start_attack:
            winner,loser=opposite_player,current_player
        else:
            winner,loser=current_player,opposite_player
    #현재 플레이어의 공격력이 높은 경우
    else:
        winner,loser=current_player,opposite_player
    
    winning_point=abs(attack_point-opposite_attack_point)

2-1-1: 진 플레이어의 이동

진 플레이어는 다음 칸으로 이동하게 되는데, 이때 다음 칸이 경계를 넘어서거나 다른 플레이어가 있는 경우 빈칸을 찾을때 까지 오른쪽으로 계속 회전한다. 진 플레이어는 다음 칸으로 이동하기 전에 총을 소유하고 있으면 그 자리에 총을 버리고, 만약 이동한 다음 칸에 총이 있는 경우 해당 총을 소유한다.

#진 플레이어
loser_row,loser_col,loser_dir,_,loser_gun_info=players[loser]

loser_next_row=loser_row+dy[loser_dir]
loser_next_col=loser_col+dx[loser_dir]

#범위를 넘어서거나 해당 자리에 플레이어가 있는 경우 오른쪽으로 90도씩 회전해서 빈칸을 찾도록한다.
while loser_next_row < 0 or loser_next_row >=n or loser_next_col < 0 or loser_next_col >=n or player_map[loser_next_row][loser_next_col] !=-1:
    loser_dir=(loser_dir+1)%4
    loser_next_row=loser_row+dy[loser_dir]
    loser_next_col=loser_col+dx[loser_dir]  

players[loser][2]=loser_dir

#새로운 자리로 이동시킨다.
players[loser][0]=loser_next_row
players[loser][1]=loser_next_col
player_map[loser_next_row][loser_next_col]=loser

#총을 버리고
heappush(gun_map[loser_row][loser_col],-loser_gun_info)
players[loser][4]=0
#새로운 자리에 총이 있는 경우 먹는다.
if gun_map[loser_next_row][loser_next_col] != []:
    players[loser][4]=-1*heappop(gun_map[loser_next_row][loser_next_col])

2-1-2: 이긴 플레이어의 이동

이긴 플레이어는 합산 공격력의 차이 만큼을 포인트로 얻고, 해당 격자에 있는 총들 중에서 가장 높은 공격력의 총을 소유한다.

#승리한 플레이어
winner_row,winner_col,winner_dir,_,winner_gun_info=players[winner]
points[winner]+=winning_point
heappush(gun_map[winner_row][winner_col],-winner_gun_info)
#가장 높은 공격력의 총을 소유한다.
players[winner][4]=-1*heappop(gun_map[winner_row][winner_col])

#플레이어맵에 이긴 사용자를 입력한다.
player_map[winner_row][winner_col]=winner

2-2: 이동한 다음 칸에 플레이어가 없는 경우

현재 사용자가 이동한 다음칸에 플레이어가 없고, 총이 있는 경우 가장 높은 공격력의 총을 소유한다.

elif gun_map[next_row][next_col] != []:
#가장 높은 공격력의 총을 소유한다.
heappush(gun_map[next_row][next_col],-gun_info)
players[current_player][4]=-1*heappop(gun_map[next_row][next_col])

Solution

from heapq import heappush,heappop
def solution():
    gun_map=[[[] for _ in range(n)] for _ in range(n)]
    player_map=[[-1] * n for _ in range(n)]
    points=[0]*m
    dy=[-1,0,1,0]
    dx=[0,1,0,-1]

    #총이 있는 위치를 표기
    for row in range(n):
        for col in range(n):
            gun=guns[row][col]
            if gun !=0:
               heappush(gun_map[row][col],-gun)
    
    #플레이어의 위치 표기
    for num in range(m):
        players[num][0]-=1
        players[num][1]-=1
        row,col=players[num][0],players[num][1]
        player_map[row][col]=num
        #총의 정보 추가
        players[num].append(0)
    
    
    #시뮬레이션 진행
    for _ in range(k):
        for current_player in range(m):
            row,col,dir,start_attack,gun_info=players[current_player]

            #현재 공격력
            attack_point=start_attack+gun_info
            next_row=row+dy[dir]
            next_col=col+dx[dir]

            #범위를 넘어서는 경우 방향을 반대로 해서 한 칸 간다.
            if next_row < 0 or next_row >=n or next_col < 0 or next_col >=n:
                next_dir=(dir+2)%4
                players[current_player][2]=next_dir
                next_row=row+dy[next_dir]
                next_col=col+dx[next_dir]
            
            #현재 플레이어를 이동시킨다.
            players[current_player][0]=next_row
            players[current_player][1]=next_col
            player_map[row][col]=-1

            opposite_player=player_map[next_row][next_col]
            player_map[next_row][next_col]=current_player

            #해당 자리에 플레이어가 있는 경우
            if opposite_player!=-1:
                opposite_row,opposite_col,opposite_dir,opposite_start_attack,opposite_gun_info=players[opposite_player]

                #상대방의 공격력
                opposite_attack_point=opposite_start_attack+opposite_gun_info
                winner,loser=-1,-1
                #상대방의 공격력이 더 높은 경우
                if attack_point < opposite_attack_point:
                    winner,loser=opposite_player,current_player
                
                #공격력이 서로 같은 경우, 플레이어의 초기 공격력을 비교한다.
                elif attack_point == opposite_attack_point:
                    if start_attack < opposite_start_attack:
                        winner,loser=opposite_player,current_player
                    else:
                        winner,loser=current_player,opposite_player
                #현재 플레이어의 공격력이 높은 경우
                else:
                    winner,loser=current_player,opposite_player
                
                winning_point=abs(attack_point-opposite_attack_point)

                #진 플레이어
                loser_row,loser_col,loser_dir,_,loser_gun_info=players[loser]
                loser_next_row=loser_row+dy[loser_dir]
                loser_next_col=loser_col+dx[loser_dir]

                #범위를 넘어서거나 해당 자리에 플레이어가 있는 경우 오른쪽으로 90도씩 회전해서 빈칸을 찾도록한다.
                while loser_next_row < 0 or loser_next_row >=n or loser_next_col < 0 or loser_next_col >=n or player_map[loser_next_row][loser_next_col] !=-1:
                    loser_dir=(loser_dir+1)%4
                    loser_next_row=loser_row+dy[loser_dir]
                    loser_next_col=loser_col+dx[loser_dir]  
                players[loser][2]=loser_dir

                #새로운 자리로 이동시킨다.
                players[loser][0]=loser_next_row
                players[loser][1]=loser_next_col
                player_map[loser_next_row][loser_next_col]=loser

                #총을 버리고
                heappush(gun_map[loser_row][loser_col],-loser_gun_info)
                players[loser][4]=0
                #새로운 자리에 총이 있는 경우 먹는다.
                if gun_map[loser_next_row][loser_next_col] != []:
                    players[loser][4]=-1*heappop(gun_map[loser_next_row][loser_next_col])

                #승리한 플레이어
                winner_row,winner_col,winner_dir,_,winner_gun_info=players[winner]
                points[winner]+=winning_point
                heappush(gun_map[winner_row][winner_col],-winner_gun_info)
                #가장 높은 공격력의 총을 소유한다.
                players[winner][4]=-1*heappop(gun_map[winner_row][winner_col])

                #플레이어맵에 이긴 사용자를 입력한다.
                player_map[winner_row][winner_col]=winner


            #플레이어는 없고
            elif gun_map[next_row][next_col] != []:
                #가장 높은 공격력의 총을 소유한다.
                heappush(gun_map[next_row][next_col],-gun_info)
                players[current_player][4]=-1*heappop(gun_map[next_row][next_col])


    print(*points)  
        
if __name__ == "__main__":
    n,m,k=map(int,input().split())
    guns=[list(map(int,input().split())) for _ in range(n)]
    players=[list(map(int,input().split())) for _ in range(m)]

    solution()

댓글남기기