N x M 크기의 행렬 모양의 게임 맵이 있습니다. 이 맵에는 내구도를 가진 건물이 각 칸마다 하나씩 있습니다. 적은 이 건물들을 공격하여 파괴하려고 합니다. 건물은 적의 공격을 받으면 내구도가 감소하고 내구도가 0이하가 되면 파괴됩니다. 반대로, 아군은 회복 스킬을 사용하여 건물들의 내구도를 높이려고 합니다.
적의 공격과 아군의 회복 스킬은 항상 직사각형 모양입니다.
예를 들어, 아래 사진은 크기가 4 x 5인 맵에 내구도가 5인 건물들이 있는 상태입니다.
제한사항
처음 문제를 읽자마자 와! 이건 정말 간단한걸? 생각하고 바로 풀어봤지만 역시나 효율성 테스트에서 전부 실패했다. 문제가 이렇게 쉬울리 없었다.
이 문제는 누적합을 이용하여 풀어야 효율성 테스트를 통과할 수 있었다.
그렇지않다면 skill
행의 길이 * board
크기 만큼의 연산이 필요해진다.
예시로
길이가 7이고 각 0으로 초기화된 배열 a
가 있다.
a = [0, 0, 0, 0, 0, 0, 0]
이때 a[2:4]
의 요소의 값을 2 만큼 더해주고 싶다면
[0, 0, 2, 0, 0, -2, 0]
로 표현한 뒤 누적합을 계산하면된다.
[0, 0, 2, 2, 2, 0, 0]
원했던 a[2:4]
의 값에 2를 더한 배열이 되었다.
이 방법을 응용하여 이 문제에 적용하면된다.
문제에서는 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, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
만약 (1,1)
에서 (3,4)
까지의 값을 3만큼 더하고 싶다면
[[0, 0, 0, 0, 0, 0],
[0, 3, 0, 0, 0, -3],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, -3, 0, 0, 0, 3],
[0, 0, 0, 0, 0, 0]]
로 표현한 뒤 각 행, 열을 차례로 누적합하여 계산하면 된다.
행 먼저 누적합하여 계산하면
[[0, 0, 0, 0, 0, 0],
[0, 3, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, -3, -3, -3, -3, 0],
[0, 0, 0, 0, 0, 0]]
열을 누적합하여 계산하면
[[0, 0, 0, 0, 0, 0],
[0, 3, 3, 3, 3, 0],
[0, 3, 3, 3, 3, 0],
[0, 3, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
이 되어 원하는 결과를 얻을 수 있다.
문제를 풀 때 r2+1
과 c2+1
이 board
의 인덱스 범위에서 벗어나는 경우가 발생하여서
board
의 행과 열보다 1씩 큰 2차원 배열 temp
를 만든 뒤 temp
에서 모든 누적합을 계산하고 마지막에 board
에 더하여 계산하였다.
#include <string>
#include <vector>
using namespace std;
int solution(vector<vector<int>> board, vector<vector<int>> skill) {
int answer = 0;
vector temp(board.size()+1, vector<int>(board[0].size()+1, 0));
for (auto i: skill){
int r1 = i[1];
int c1 = i[2];
int r2 = i[3];
int c2 = i[4];
int degree = i[5];
if (i[0] == 1) degree *= -1;
temp[r1][c1] += degree;
temp[r1][c2+1] -= degree;
temp[r2+1][c1] -= degree;
temp[r2+1][c2+1] += degree;
}
for (int i=0; i < temp.size(); i++){
for (int j=1; j < temp[0].size(); j ++){
temp[i][j] += temp[i][j-1];
}
}
for (int i=1; i < temp.size(); i++){
for (int j=0; j < temp[0].size(); j ++){
temp[i][j] += temp[i-1][j];
}
}
for (int i=0; i < board.size(); i++){
for (int j=0; j < board[0].size(); j ++){
if (board[i][j] + temp[i][j] > 0)
answer++;
}
}
return answer;
}