Algorithm/Implementation

[백준 1986번] 체스

킹우현 2023. 9. 30. 11:59

 

1986번: 체스

첫째 줄에는 체스 판의 크기 n과 m이 주어진다. (1 ≤ n, m ≤ 1000) 그리고 둘째 줄에는 Queen의 개수와 그 개수만큼의 Queen의 위치가 입력된다. 그리고 마찬가지로 셋째 줄에는 Knight의 개수와 위치,

www.acmicpc.net

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

# Knight, Queen, Pawn의 개수는 각각 100을 넘지 않는 음이 아닌 정수
queen_list = list(map(int,input().split()))
knight_list = list(map(int,input().split()))
pawn_list = list(map(int,input().split()))

# Queen은 가로,세로,대각선으로 이동 가능 / 장애물 통과 X
# Knight는 2x3 직사각형의 반대쪽 꼭짓점으로 이동 가능 / 장애물 통과 O

queen_count = queen_list.pop(0)
knight_count = knight_list.pop(0)
pawn_count = pawn_list.pop(0)

dx = [-1,1,0,0,-1,1,-1,1]
dy = [0,0,-1,1,-1,1,1,-1]

k_dx = [-1,-2,-2,-1,1,1,2,2]
k_dy = [-2,-1,1,2,-2,2,-1,1]

queen_list = [(x,y) for x,y in zip(queen_list[0::2], queen_list[1::2])]
knight_list = [(x,y) for x,y in zip(knight_list[0::2], knight_list[1::2])]
pawn_list = [(x,y) for x,y in zip(pawn_list[0::2], pawn_list[1::2])]

area = [[0]*m for _ in range(n)]

answer = 0

for pawn_x,pawn_y in pawn_list:
    area[pawn_x-1][pawn_y-1] = -1

for queen_x, queen_y in queen_list:
    area[queen_x-1][queen_y-1] = -1

for knight_x, knight_y in knight_list:
    area[knight_x-1][knight_y-1] = -1


def queen_move(x,y): # 퀸 이동 함수

    for i in range(8):
        nx, ny = x, y

        while 0 <= nx < n and 0 <= ny < m:
            nx = nx + dx[i]
            ny = ny + dy[i]
            if 0 <= nx < n and 0 <= ny < m:
                if area[nx][ny] == -1:
                    break
                area[nx][ny] = 1

def knight_move(x,y): # 나이트 이동 함수
    for i in range(8):
        nx = x + k_dx[i]
        ny = y + k_dy[i]
        if 0 <= nx < n and 0 <= ny < m:
            area[nx][ny] = 1

for queen_x,queen_y in queen_list: # 퀸 이동
    queen_move(queen_x-1,queen_y-1)

for knight_x,knight_y in knight_list: # 나이트 이동
    knight_move(knight_x-1,knight_y-1)

for i in range(n):
    for j in range(m):
        if area[i][j] == 0:
            answer += 1

print(answer)

이번 문제는 Queen, Knight, Pawn의 위치 좌표가 주어졌을 때, 안전한 칸이 몇 칸인지 구하는 문제이다.

 

각 기물의 좌표를 따로 입력받는 것이 아니라 기물의 개수와 동시에 입력받아서 좌표를 리스트화 하는데 시간이 조금 걸리긴 했지만 나머지는 단순한 구현문제이다.(리스트에 있는 요소들을 2개로 묶을 때 '리스트 컴프리핸션'과 'zip함수'를 사용하면 좋다)

 

문제를 해결하기 위해 Queen의 움직임과 Knight의 움직임을 함수로 구현하였고, 처음에는 조건문과 반복문으로 풀이하려고 하다가 2차원 배열에서의 이동을 효율적으로 해줄 수 있는 dx와 dy를 사용한 풀이가 떠올라 효율적으로 코드를 작성했다.

 

그리고 1가지 실수한 점이 존재했는데, 바로 "퀸이 이동을 멈추는 조건"이었다.

 

처음에는 퀸이 이동을 멈추는 조건을 '빈칸이 아닐 때, 즉 기물이 이미 방문했거나 장애물인 경우(area[nx][ny] != 0)'로 설정했는데, 위 설명을 보고나니 퀸이 이미 방문했다고 해서 다른 퀸이 이동하지 못할 이유가 없다는 것을 깨닫고 '장애물인 경우(area[nx][ny] == -1)'에만 멈추도록 설정해주었다.

 

2차원 배열에서의 이동을 연습할 수 있는 구현문제였다 :)

 

배운 점 및 느낀 점

  1. 두 그룹의 데이터를 서로 묶어줄 때 'zip함수'를 사용할 것
  2. 2차원 배열에서의 이동을 다루는 문제는 dx, dy를 사용할 것
  3. 문제가 풀리지 않을 때는 조건을 잘못 설정하지는 않았는지 점검할 것