Algorithm/Swift

[백준 16931] 겉넓이 구하기 (Swift)

Minny27 2021. 7. 6. 15:27

문제 : 

https://www.acmicpc.net/problem/16931

 

16931번: 겉넓이 구하기

크기가 N×M인 종이가 있고, 종이는 1×1크기의 칸으로 나누어져 있다. 이 종이의 각 칸 위에 1×1×1 크기의 정육면체를 놓아 3차원 도형을 만들었다. 종이의 각 칸에 놓인 정육면체의 개수가 주어

www.acmicpc.net

 

1. 문제 이해하기

  • 입력으로 좌, 우(n, m), 그리고 각 칸마다 올려진 블록의 개수를 2차원 배열로 주어진다.
  • 총 겉넓이(위, 아래, 앞, 뒤, 좌, 우 넓이) 출력하기

 

2. 문제 풀이 생각하기

  1. 먼저 위아래는 (2차원 배열의 행 * 열 * 2), 좌, 우는 (좌의 겉넓이 * 2), 앞, 뒤도 (앞의 겉넓이 * 2) 구하면 된다고 생각했습니다.
  2. 처음에는 한 방향의 겉넓이를 (각 행 또는 각 열의 가장 큰 값의 합)으로 구하면 된다고 생각했는데 예제 입력 2를 보면 60이 나오는데 안 보이는 부분에서의 넓이를 따로 구해서 더해주어야 한다는 것을 뒤늦게 깨달았습니다.
  3. 그래서 좌측 겉넓이로 예를 들어보면 열 = 0일 때 겉넓이를 더하고, 열 = 1번째부터는 이전 칸(g[i][j - 1])과 현재 칸(g[i][j])의 높이를 비교해서 현재 칸이 높으면 차이만큼 tmpSum에 더하고 최종적으로 좌, 우 겉넓이 합(tmpSum * 2)을 ans에 더합니다.

 

총 6군데의 겉넓이를 구해야 하며, 안 보이는 겉넓이를 고려해서 구해야 합니다.

 

3. 차근차근 구현하기

import Foundation

var matrix = readLine()!.components(separatedBy : " ")
let (n, m) = (Int(matrix[0])!, Int(matrix[1])!)
var g = [[Int]]() // graph
var ans = n * m * 2
for _ in 0..<n {
    let line = readLine()!.components(separatedBy : " ").map{Int(String(($0)))!}
    g.append(line)
}

// 좌, 우 겉넓이 구하기 -> 좌 겉넓이 * 2
for i in 0..<n {
    var tmpSum = 0 // 행별 합
    for j in 0..<m {
        if j == 0 {
            tmpSum += g[i][j]
        }
        // 현재 개수와 이전 개수를 비교
        else if g[i][j - 1] < g[i][j] {
            tmpSum += g[i][j] - g[i][j - 1]
        }
    }
    ans += 2 * tmpSum
}

// 앞, 뒤 겉넓이 구하기 -> 앞 겉넓이 * 2
for j in 0..<m {
    var tmpSum = 0 // 열별 합
    for i in 0..<n {
        if i == 0 {
            tmpSum += g[i][j]
        }
        // 현재 개수와 이전 개수를 비교
        else if g[i - 1][j] < g[i][j] {
            tmpSum += g[i][j] - g[i - 1][j]
        }
    }
    ans += 2 * tmpSum
}
print(ans)

// Test Case
//3 3
//4 1 3
//2 2 2
//2 2 2
//
//답 : 56
//
//3 5
//4 3 1 3 4
//1 1 1 1 1
//1 1 1 1 1
//
//답 : 78

 

4. 피드백

  • '안 보이는 부분을 구해야 한다'는 생각을 빠르게 못해서 아쉬웠고, else if 부분에서 처음에는 g[i][j] < g[i][j + 1] 식의 현재 칸의 겉넓이와 다음 칸의 겉넓이 값을 비교해서 에러가 있었는데 이전 값을 비교해야 된다는 것을 늦게 깨달았습니다.