본문 바로가기

코딩테스트/프로그래머스

[프로그래머스] 파괴되지 않은 건물

728x90
반응형


📌 문제 설명

N x M 크기의 행렬 모양의 게임 맵이 있습니다. 이 맵에는 내구도를 가진 건물이 각 칸마다 하나씩 있습니다. 적은 이 건물들을 공격하여 파괴하려고 합니다. 건물은 적의 공격을 받으면 내구도가 감소하고 내구도가 0이하가 되면 파괴됩니다. 반대로, 아군은 회복 스킬을 사용하여 건물들의 내구도를 높이려고 합니다.
적의 공격과 아군의 회복 스킬은 항상 직사각형 모양입니다.

 

건물의 내구도를 나타내는 2차원 정수 배열 board와 적의 공격 혹은 아군의 회복 스킬을 나타내는 2차원 정수 배열 skill이 매개변수로 주어집니다. 적의 공격 혹은 아군의 회복 스킬이 모두 끝난 뒤 파괴되지 않은 건물의 개수를 return하는 solution함수를 완성해 주세요.

 

📌 제한 사항

  • 1 ≤ board의 행의 길이 (= N) ≤ 1,000
  • 1 ≤ board의 열의 길이 (= M) ≤ 1,000
  • 1 ≤ board의 원소 (각 건물의 내구도) ≤ 1,000
  • 1 ≤ skill의 행의 길이 ≤ 250,000
  • skill의 열의 길이 = 6
  • skill의 각 행은 [type, r1, c1, r2, c2, degree]형태를 가지고 있습니다.
    • type은 1 혹은 2입니다.
      • type이 1일 경우는 적의 공격을 의미합니다. 건물의 내구도를 낮춥니다.
      • type이 2일 경우는 아군의 회복 스킬을 의미합니다. 건물의 내구도를 높입니다.
    • (r1, c1)부터 (r2, c2)까지 직사각형 모양의 범위 안에 있는 건물의 내구도를 degree 만큼 낮추거나 높인다는 뜻입니다.
      • 0 ≤ r1 ≤ r2 < board의 행의 길이
      • 0 ≤ c1 ≤ c2 < board의 열의 길이
      • 1 ≤ degree ≤ 500
      • type이 1이면 degree만큼 건물의 내구도를 낮춥니다.
      • type이 2이면 degree만큼 건물의 내구도를 높입니다.
  • 건물은 파괴되었다가 회복 스킬을 받아 내구도가 1이상이 되면 파괴되지 않은 상태가 됩니다. 즉, 최종적으로 건물의 내구도가 1이상이면 파괴되지 않은 건물입니다.
  • 1 ≤ board의 행의 길이 (= N) ≤ 100
  • 1 ≤ board의 열의 길이 (= M) ≤ 100
  • 1 ≤ board의 원소 (각 건물의 내구도) ≤ 100
  • 1 ≤ skill의 행의 길이 ≤ 100
  • 1 ≤ degree ≤ 100

 

📌 입출력 예

 

board skill result
[[5,5,5,5,5],[5,5,5,5,5],[5,5,5,5,5],[5,5,5,5,5]] [[1,0,0,3,4,4],[1,2,0,2,3,2],[2,1,0,3,1,2],[1,0,1,3,3,1]] 10
[[1,2,3],[4,5,6],[7,8,9]] [[1,1,1,2,2,4],[1,0,0,1,1,2],[2,2,0,2,0,100]] 6

 

🔗 문제 링크

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

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


반응형

💡 풀이 아이디어

    • 누적합
      • 2차원 배열에서 (x1,y1)부터 (x2,y2)까지 n만큼의 변화는 (x1,y1)에 +n, (x1,y2+1)에 -n, (x2+1,y1)에 -n, (x2+1,y2+1)에 +n을 한 것과 같다.
    • 풀이 참고 : https://tech.kakao.com/posts/488
 

2022 카카오 신입 공채 1차 온라인 코딩테스트 for Tech developers 문제해설 - tech.kakao.com

지난 2021년 9월 11일 토요일 오후 2시부터 7시까지 5시간 동안 2022 ...

tech.kakao.com

📝 최종 풀이

  • 기존의 board보다 행과 열을 하나씩 늘린 sum을 0으로 초기화합니다.
  • 누적합의 아이디어에 따라 skill의 정보를 sum의 원소에 적용합니다.
  • sum을 위에서 아래로 누적합니다.
  • sum을 왼쪽에서 오른쪽으로 누적합니다.
  • 누적합이 완료된 sum을 board와 합칩니다. 이 때, 원소가 0을 초과하는 경우 answer을 증가시킵니다.
  • 최종적으로 파괴되지 않은 건물의 개수인 answer을 return 합니다.

728x90

👩‍💻 코드

#include <string>
#include <vector>
#include <iostream>

using namespace std;

int solution(vector<vector<int>> board, vector<vector<int>> skill) {
    int n = board.size();
    int m = board[0].size();
    int answer = 0;
    vector<vector<int>> sum (n+1, vector<int>(m+1, 0));
    
    for(auto s : skill){
        int type = s[0];
        int r1 = s[1];
        int c1 = s[2];
        int r2 = s[3];
        int c2 = s[4];
        int degree = type == 1 ? s[5] * -1 : s[5];
        
        sum[r1][c1] += degree;
        sum[r2+1][c2+1] += degree;
        sum[r1][c2+1] += degree * -1;
        sum[r2+1][c1] += degree * -1;
    }
    
    for(int i=0; i<=m; i++){
        for(int j=1; j<=n; j++){
            sum[j][i] += sum[j-1][i];
        }
    }
    
    for(int i=0; i<=n; i++){
        for(int j=1; j<=m; j++){
            sum[i][j] += sum[i][j-1];
        }
    }
    
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            board[i][j] += sum[i][j];
                
            if(board[i][j] > 0){
                answer++;
            }
        }
    }
    
    return answer;
}
728x90
반응형