https://school.programmers.co.kr/learn/courses/30/lessons/92344
문제 설명
[본 문제는 정확성과 효율성 테스트 각각 점수가 있는 문제입니다.]
N x M 크기의 행렬 모양의 게임 맵이 있습니다. 이 맵에는 내구도를 가진 건물이 각 칸마다 하나씩 있습니다. 적은 이 건물들을 공격하여 파괴하려고 합니다. 건물은 적의 공격을 받으면 내구도가 감소하고 내구도가 0이하가 되면 파괴됩니다. 반대로, 아군은 회복 스킬을 사용하여 건물들의 내구도를 높이려고 합니다.
적의 공격과 아군의 회복 스킬은 항상 직사각형 모양입니다.
예를 들어, 아래 사진은 크기가 4 x 5인 맵에 내구도가 5인 건물들이 있는 상태입니다.
첫 번째로 적이 맵의 (0,0)부터 (3,4)까지 공격하여 4만큼 건물의 내구도를 낮추면 아래와 같은 상태가 됩니다.
두 번째로 적이 맵의 (2,0)부터 (2,3)까지 공격하여 2만큼 건물의 내구도를 낮추면 아래와 같이 4개의 건물이 파괴되는 상태가 됩니다.
세 번째로 아군이 맵의 (1,0)부터 (3,1)까지 회복하여 2만큼 건물의 내구도를 높이면 아래와 같이 2개의 건물이 파괴되었다가 복구되고 2개의 건물만 파괴되어있는 상태가 됩니다.
마지막으로 적이 맵의 (0,1)부터 (3,3)까지 공격하여 1만큼 건물의 내구도를 낮추면 아래와 같이 8개의 건물이 더 파괴되어 총 10개의 건물이 파괴된 상태가 됩니다. (내구도가 0 이하가 된 이미 파괴된 건물도, 공격을 받으면 계속해서 내구도가 하락하는 것에 유의해주세요.)
최종적으로 총 10개의 건물이 파괴되지 않았습니다.
건물의 내구도를 나타내는 2차원 정수 배열 board와 적의 공격 혹은 아군의 회복 스킬을 나타내는 2차원 정수 배열 skill이 매개변수로 주어집니다. 적의 공격 혹은 아군의 회복 스킬이 모두 끝난 뒤 파괴되지 않은 건물의 개수를 return하는 solution함수를 완성해 주세요.
문제 자체는 어렵지 않지만 효율성 테스트를 통과하기 위해 누적합 알고리즘을 사용해서 풀어야하는 문제였다.
사각형의 범위를 모두 훑을 수 있는 누적합이라 기억해두는 것이 좋을 것 같다.
예로 들어, 4x5 내구도에서 (1,1) 부터 (2,3) 까지 내구도를 2 만큼 늘린다면 다음과 같다.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 => 0 2 0 0 -2 => 0 2 2 2 0 => 0 2 2 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0
0 0 0 0 0 0 -2 0 0 2 0 -2 -2 -2 0 0 0 0 0 0
(1) (2) (3)
(1) 과정에서 위와 같이 표시하고 (2) 과정에서 행 단위로 누적합을 진행한다.
(3) 과정에서 열 단위로 누적합을 진행하고 확인하면 내구도에서 (1,1)부터 (2,3)까지 내구도가 2씩 늘어난 것을 확인할 수 있다!
<< 전체 코드 >>
def solution(board, skill):
answer = 0
hp = [[0 for j in range(len(board[0]))] for i in range(len(board))]
for li in skill:
if li[0] == 1:
li[5] *= -1
hp[li[1]][li[2]] += li[5]
if li[4]+1 < len(board[0]):
hp[li[1]][li[4]+1] += -li[5]
if li[3]+1 < len(board):
hp[li[3]+1][li[2]] += -li[5]
if li[3]+1 < len(board) and li[4]+1 < len(board[0]):
hp[li[3]+1][li[4]+1] += li[5]
# 행단위로 누적합
for i in range(len(board)):
for j in range(1, len(board[0])):
hp[i][j] += hp[i][j-1]
# 열단위로 누적합
for j in range(len(board[0])):
for i in range(1, len(board)):
hp[i][j] += hp[i-1][j]
for i in range(len(board)):
for j in range(len(board[0])):
board[i][j] += hp[i][j]
if board[i][j] > 0:
answer += 1
return answer
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스 Level3] 합승 택시 요금 - 파이썬(Python) - 2021 KAKAO BLIND RECRUITMENT (0) | 2022.11.30 |
---|---|
[프로그래머스 Level3] 등굣길 - C언어(C++) (0) | 2022.11.30 |
[프로그래머스 Level3] 거스름돈 - 파이썬(Python) (0) | 2022.11.21 |
[프로그래머스 Level1] 숫자 짝꿍 - 파이썬(Python) - 연습문제 (0) | 2022.11.12 |
[프로그래머스 Level2] 수식 최대화 - 파이썬(Python) - 2020 카카오 인턴십 (0) | 2022.10.31 |