처음에 떠오른 생각은 그냥 다 계산해주는 거다. 너비 우선 탐색으로 일일히 구하고 양수인 것만 세주면 그게 답이잖아?
하지만, 여기서 간과하면 안 될 조건이 있으니 바로 해당 문제는 정확성과 효율성 테스트가 각각 있는 문제라는 거다. 효율성 테스트! 때문에 이렇게 풀면 무조건 통과를 못 한다. 이제껏 효율성 테스트에서 눈물을 흘렸던 나의 본능이랄까...
그럼 효율성 테스트를 통과하기 위해서 어떻게 문제를 풀어야 하지?
모르겠다.
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ....
그래서 일단은 정확성 테스트라도 통과해보자 싶은 마음으로 깊이 우선 탐색을 이용해 코드를 짰다.
사실 깊이 우선 탐색을 이용해 효율성 테스트를 무시한 풀이는 굉장히 간단하다.
효율성 테스트를 어떻게 풀건지 해답을 구하기 위해 다른 사람의 풀이를 참고했다.
https://jangcenter.tistory.com/121
해당 풀이에서는 누적합을 이용해서 풀었는데, 일단 누적합 기준의 위치를 변경한 후에 맨 마지막에 변화량을 합산하는 방식을 사용했다.
간단하게 말하자면 합을 할 범위의 끝점에 변경 degree를 미리 놓아두고 맨 마지막에 상하좌우로 전부 계산해주는 풀이다.
이건 더 정확한 설명을 위해 위의 링크를 참고하길 바란다. 그림도 있어서 이해가 쉽게 될 것이다.
import java.util.*;
class pair{
int row;
int col;
pair(int row, int col){
this.row = row;
this.col = col;
}
}
class Solution {
public static int[][] map;
public static int[] dR = {-1, 0, 1, 0}; //북동남서
public static int[] dC = {0, 1, 0, -1}; //북동남서
public static boolean[][] visit;
public static int lengthR, lengthC;
public int solution(int[][] board, int[][] skill) {
int answer = 0;
map = new int[board.length][board[0].length];
lengthR = map.length;
lengthC = map[0].length;
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
map[i][j] = board[i][j];
}
}
for(int i=0; i<skill.length; i++){
int[] cSkill = skill[i];
int type = cSkill[0];
int startR = cSkill[1];
int startC = cSkill[2];
int endR = cSkill[3];
int endC = cSkill[4];
int cDegree = cSkill[5];
visit = new boolean[lengthR][lengthC];
//공격을 의미
if(type == 1){
cDegree *= -1;
}
bfs(startR, startC, endR, endC, cDegree);
}
answer = check();
return answer;
}
public static void bfs(int startR, int startC, int endR, int endC, int degree){
Queue<pair> queue = new LinkedList<>();
visit[startR][startC] = true;
queue.add(new pair(startR, startC));
map[startR][startC] += degree;
//System.out.println("current " + startR + " " + startC + " " + degree);
while(!queue.isEmpty()){
pair current = queue.poll();
int currentR = current.row;
int currentC = current.col;
for(int i=0; i<4; i++){
int newR = currentR + dR[i];
int newC = currentC + dC[i];
if(newR >= startR && newR <= endR && newC >= startC && newC <= endC){
if(visit[newR][newC] == false){
map[newR][newC] += degree;
//System.out.println("move to " + newR + " " + newC + " " + degree);
visit[newR][newC] = true;
queue.add(new pair(newR, newC));
}
}
}
}
//System.out.println();
}
public static int check(){
int answer = 0;
for(int i=0; i<lengthR; i++){
for(int j=0; j<lengthC; j++){
if(map[i][j] > 0){
//System.out.println(i + " " + j);
answer++;
}
}
}
return answer;
}
}
import java.util.*;
class Solution {
public static int[][] map;
public static int lengthR, lengthC;
public int solution(int[][] board, int[][] skill) {
int answer = 0;
map = new int[board.length+2][board[0].length+2];
lengthR = board.length;
lengthC = board[0].length;
for(int i=0; i<skill.length; i++){
int[] current = skill[i];
int type = current[0];
int startR = current[1];
int startC = current[2];
int endR = current[3];
int endC = current[4];
int degree = current[5];
if(type == 1){
degree *= -1;
}
map[startR][startC] += degree;
map[startR][endC+1] += degree*-1;
map[endR+1][startC] += degree*-1;
map[endR+1][endC+1] += degree;
}
ope();
for(int i=0; i<lengthR; i++){
for(int j=0; j<lengthC; j++){
if(map[i][j] + board[i][j] > 0){
answer++;
}
}
}
return answer;
}
public static void ope(){
//상하
for(int i=1; i<lengthR; i++){
for(int j=0; j<lengthC; j++){
//위에 있는 값과 현재 값을 더해준다.
map[i][j] += map[i-1][j];
}
}
//좌우
for(int j=1; j<lengthC; j++){
for(int i=0; i<lengthR; i++){
//왼쪽에 있는 값과 현재 값을 더해준다.
map[i][j] += map[i][j-1];
}
}
}
}
https://jangcenter.tistory.com/121
솔직히 이런 종류의 문제를 예전에 풀어본 적이 없다면 테스트를 볼 때 당장 떠올리지 못할 풀이 같다. ㅎㅎ... 하지만 난 이제 풀었으니까 됐지! 나중에 몇 번 더 풀어야지.