본문 바로가기
알고리즘 문제 풀이/백준

백준 20002 사과나무 Kotlin (2차원 누적 합)

by 옹구스투스 2022. 7. 11.
반응형

문제 출처 : https://www.acmicpc.net/problem/20002

 

20002번: 사과나무

N × N 크기의 정사각형 모양 과수원이 있고, N × N 개의 사과나무가 1 × 1 크기의 간격으로 모든 칸에 심어져있다. 농부 형곤이가 가을을 맞아 사과를 수확하려는데, 땅주인 신영이가 "너는 과수원

www.acmicpc.net

문제

N × N 크기의 정사각형 모양 과수원이 있고, N × N 개의 사과나무가 1 × 1 크기의 간격으로 모든 칸에 심어져있다.

농부 형곤이가 가을을 맞아 사과를 수확하려는데, 땅주인 신영이가 "너는 과수원 내에 사과나무를 K × K 의 크기의 정사각형 모양으로만 수확해 가져갈 수 있어, 이때 K는 1보다 크거나 같고 N보다 작거나 같은 정수라구! 나머지는 내가 먹을께! 하하!" 라고 통보했다.

하나의 사과나무를 수확할 때, 사과를 통해 얻을 수 있는 이익과 노동비로 빠져나가는 손해가 동시에 이루어진다.

그래서 형곤이는 나무의 위치를 좌표로 하여, 사과를 통해 얻은 이익과 노동비를 더한 총이익을 2차원 배열의 형태로 정리했다.

악독한 땅주인 신영이로부터 고통받는 귀여운 형곤이에게 최대 총이익을 안겨주고 싶은 당신, 형곤이를 도와주자!

입력

첫 번째 줄에는 과수원의 크기 N이 주어진다. (1 ≤ N ≤ 300)

두 번째 줄부터 N + 1번째 줄까지, 해당 나무를 수확했을 때 얻을 수 있는 총이익을 표시한다.

총이익은 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

출력

첫 번째 줄에 최댓값을 출력한다.

알고리즘 분류

풀이

정말 간단한 2차원 누적 합 문제이다.

k*k크기의 구간의 합을 구하려면 누적합 배열에서

sum[r][c] - sum[r-k][c] - sum[r][c-k] + sum[r-k][c-k]를 해주면 된다.

우선 2차원 누적 합 배열을 만들기 위해선 열에 대한 누적 합, 행에 대한 누적 합을 각각 해주어야 하는데,

이는 sum[r][c] = sum[r][c](초기 입력 값) -sum[r-1][c-1] + sum[r-1][c] + sum[r][c-1]로 표현하면 한 번의 2중 포문으로 구할 수 있다.

이렇게 2차원 누적 합을 구해놓고 1부터n까지의 k사이즈에 대한 k*k 구간의 누적 합을 출력하면 된다.

왜 이러한 식이 나오는지 모른다면 2차원 누적 합의 개념부터 보면 된다.

코드

val br = System.`in`.bufferedReader()
fun getIntList() = br.readLine().split(' ').map { it.toInt() }
fun getInt() = br.readLine().toInt()

fun main() = with(System.out.bufferedWriter()) {
    //input
    val n = getInt()
    val graph = Array(n+1) { IntArray(n+1) }
    for(r in 1 .. n){
        val input = getIntList()
        for(c in 1 .. n){
            graph[r][c] = input[c-1] - graph[r-1][c-1] + graph[r][c-1] + graph[r-1][c]
        }
    }

    var answer = -1000
    for (i in 1 .. n) {
        for (r in i .. n) {
            for (c in i .. n) {
                answer = answer.coerceAtLeast(graph[r][c] + graph[r-i][c-i] - graph[r-i][c] - graph[r][c-i])
            }
        }
    }
    write("$answer")
    close()
}
반응형

댓글