[백준 15724] 주지수

 

15724번: 주지수

네모 왕국의 왕인 진경대왕은 왕국의 영토를 편하게 통치하기 위해서 1X1의 단위 구역을 여러 개 묶어서 하나의 거대 행정구역인 주지수(州地數, 마을의 땅을 셈)를 만들 예정이다. 진경대왕은

www.acmicpc.net

1. 문제 요약

- 제한시간 2초
- N x M 사이즈의 단위구역 내에 각 값을 입력받고
    - 이어서 시작행, 시작열, 끝행, 끝열을 입력받는다
해당 범위 내의 사람들의 수의 합을 구하는 문제이다

 

2. 아이디어 (문제 접근법)

[아이디어-1]
- int answer 를 만들어 범위 내의 합을 저장한다
- for 시작행-1 ~ 끝행-1
    for 시작열-1 ~ 끝열-1
        answer += 해당 위치 값
[아이디어-2]
- 시간을 줄이는 방법
    1. (0, 0) 에서 시작하는 범위의 합을 그때그때 기록해둔다
        -> 순회 시간을 줄이기 위함
        -> sumArr[x][y]를 새로 입력받기 위해서는
            입력받는 값 + sunArr[x][y-1] + sumArr[x-1][y] - sumArr[x-1][y-1]
    2. DP 과정이 인구 수를 궁금해하는 직사각형 범위가 주어질 때가 아니라
                단위 구역 내에 살고 있는 사람 수를 입력받을 때 적용된다

이후 board 가 필요 없다고 판단하여 삭제
                    메모리        시간
board 가 있을 때 -> 123328 KB  864 ms
board 가 없을 때 -> 120120 KB  952 ms

 

3. 어려움 및 해결

[아이디어-1] -> 시간초과 발생
            -> 영토의 크기는 (1 ≤ N, M ≤ 1,024) 으로 잘 체감이 안되었는데
            -> 다시 확인하니 직사각형 범위의 개수 K(1 ≤ K ≤ 100,000) 였다
            -> 시간을 줄일 수 있는 방법을 고안해봄 ([아이디어-2]로)
[아이디어-2] -> sumArr[0][0]을 입력받을 때 ArrayIndexOutOfBoundsException 발생 가능하므로
            sumArr 의 크기를 int[N+1][M+1] 로 입력받아 sum[1][1]부터 입력받는다

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BOJ_15724_주지수 {
    static int[][] sumArr;

    static StringBuffer sb = new StringBuffer();

    static int N;
    static int M;

    public static int dp(int startRow, int startColumn, int endRow, int endColumn){
        return sumArr[endRow][endColumn] + sumArr[startRow-1][startColumn-1] - sumArr[endRow][startColumn-1] - sumArr[startRow-1][endColumn];
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stk;

        stk = new StringTokenizer(br.readLine());
        N = Integer.parseInt(stk.nextToken());
        M = Integer.parseInt(stk.nextToken());
        sumArr = new int[N+1][M+1];

        for(int i=1; i<=N; i++){
            stk = new StringTokenizer(br.readLine());
            for(int j=1; j<=M; j++){
                sumArr[i][j] = Integer.parseInt(stk.nextToken()) + sumArr[i-1][j] + sumArr[i][j-1] - sumArr[i-1][j-1];
            }
        }

        int n = Integer.parseInt(br.readLine());
        for(int i=0; i<n; i++){
            stk = new StringTokenizer(br.readLine());
            sb.append(dp(Integer.parseInt(stk.nextToken()), Integer.parseInt(stk.nextToken()), Integer.parseInt(stk.nextToken()), Integer.parseInt(stk.nextToken())) + "\n");
        }
        if(sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb);
    }
}

'Solved > BOJ' 카테고리의 다른 글

[백준 2812] 크게 만들기  (0) 2023.05.28
[백준12865] 평범한 배낭  (0) 2023.05.25
[백준 5557] 1학년  (0) 2023.05.24
[백준 1695] 팰린드롬 만들기  (0) 2023.05.23
[백준 11055] 가장 큰 증가하는 부분수열  (0) 2023.05.20