안전지대

2024. 8. 20. 18:00코딩테스트 입문

https://school.programmers.co.kr/learn/courses/30/lessons/120866

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


문제 설명
다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.

 

지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.


제한사항

  • boardn * n 배열입니다.
  • 1 ≤ n ≤ 100
  • 지뢰는 1로 표시되어 있습니다.
  • board에는 지뢰가 있는 지역 1과 지뢰가 없는 지역 0만 존재합니다.

입출력 예

board result
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]] 16
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]] 13
[[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]] 0

입출력 예 설명
입출력 예 #1

  • (3, 2)에 지뢰가 있으므로 지뢰가 있는 지역과 지뢰와 인접한 위, 아래, 좌, 우, 대각선 총 8칸은 위험지역입니다. 따라서 16을 return합니다.

입출력 예 #2

  • (3, 2), (3, 3)에 지뢰가 있으므로 지뢰가 있는 지역과 지뢰와 인접한 위, 아래, 좌, 우, 대각선은 위험지역입니다. 따라서 위험지역을 제외한 칸 수 13을 return합니다.

입출력 예 #3

  • 모든 지역에 지뢰가 있으므로 안전지역은 없습니다. 따라서 0을 return합니다.

지뢰와 그 인근지역을 위험지대로 설정하고, 남은 안전지대의 개수를 세는 문제입니다.

총 8방향에 대해서 board의 위험지대를 갱신시키고, 그 중 0으로 멀쩡한 지대를 count 함수로 찾으면 되는 문제입니다.

입문 단계도 초기 문제들은 쉬웠는데, 뒤로 갈수록 조금씩 난이도가 올라가네요.

 

파이썬으로 문제를 풀어보겠습니다.

def solution(board):
    # 보드의 길이 초기화
    n = len(board)
    # 인근 방향 설정
    directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
    
    # 위험지역를 기록합니다.
    dangers = set()
    
    # 모든 x, y 좌표에 대해서 탐색합니다.
    for nx in range(n):
        for ny in range(n):
            # 해당 지점에 지뢰가 있을 경우
            if board[nx][ny] == 1:
                # 모든 방향에 대해서 위험지대에 추가합니다.
                for dx, dy in directions:
                    tx, ty = nx + dx, ny + dy
                    if 0 <= tx < n and 0 <= ty < n and not board[tx][ty]:
                        dangers.add((tx, ty))
                        
    # 위험지역에 포함된 x, y좌표를 보드에 표시합니다.
    for nx, ny in dangers:
        board[nx][ny] = 2
        
    # 보드의 안전지대(0)의 개수를 합산합니다.
    return sum(row.count(0) for row in board)

 

다음 과정을 통해 문제를 풀었습니다.

1. 모든 좌표에 대해서 탐색하기 위해, 우선 n과 directions를 설정해줍니다.

2. 위험지대 연산을 줄이기 위해 집합으로 관리합니다.

3. 모든 좌표에 대해 탐색을 시작합니다.

4. 지뢰가 발견되면 모든 방향에 대해 위험지대를 설정합니다. 올바른 인덱스 범위에서만 처리합니다.

5. 설정된 위험지역은 2로 설정합니다.

6. 갱신된 board에서 0의 개수를 반환합니다.

 

풀다보니 BFS 알고리즘이 생각나더라고요. 재밌는 문제였습니다.

 

 

'코딩테스트 입문' 카테고리의 다른 글

외계어 사전  (0) 2024.08.22
삼각형의 완성조건 (2)  (0) 2024.08.21
숨어있는 숫자의 덧셈 (2)  (0) 2024.08.19
다항식 더하기  (0) 2024.08.18
최댓값 만들기 (2)  (0) 2024.08.17