[백준 16931] 겉넓이 구하기 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
각 칸에 정육면체가 일정 개수씩 쌓여 있는 격자가 주어집니다. 도형의 겉넓이는 상하면과 동서남북 네 방향의 옆면을 모두 더한 값입니다.
상하면은 모든 칸에 최소 1개 이상 있으므로 격자 크기의 2배입니다. 옆면은 인접 칸과의 높이 차이만큼 겉으로 드러나며, 경계에서는 인접 높이를 0으로 봅니다.
접근법
먼저, 경계를 0으로 초기화한 행렬을 사용합니다. 이렇게 하면 경계 처리를 별도로 하지 않아도 됩니다.
다음으로, 상면의 개수를 누적합니다. 동서 방향은 각 행을 왼쪽에서 오른쪽으로 보며 높이가 증가하는 부분만 더합니다. 남북 방향도 같은 방식으로 각 열을 위에서 아래로 보며 처리합니다.
이후, 누적한 값을 2배 합니다. 이렇게 하면 상하면과 양방향 옆면이 한번에 계산됩니다.
Code
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
namespace Solution {
class Program {
static void Main(string[] args) {
var first = Console.ReadLine()!.Split();
var row = int.Parse(first[0]);
var col = int.Parse(first[1]);
var mat = new int[row + 1, col + 1];
var ans = row * col;
for (var r = 1; r <= row; r++) {
var line = Console.ReadLine()!.Split();
var sum = 0;
for (var c = 1; c <= col; c++) {
mat[r, c] = int.Parse(line[c - 1]);
if (mat[r, c] > mat[r, c - 1])
sum += mat[r, c] - mat[r, c - 1];
}
ans += sum;
}
for (var c = 1; c <= col; c++) {
var sum = 0;
for (var r = 1; r <= row; r++) {
if (mat[r, c] > mat[r - 1, c])
sum += mat[r, c] - mat[r - 1, c];
}
ans += sum;
}
Console.WriteLine(2 * ans);
}
}
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int row, col; cin >> row >> col;
vector<vi> mat(row + 1, vi(col + 1, 0));
int ans = row * col;
for (int r = 1; r <= row; r++) {
int sum = 0;
for (int c = 1; c <= col; c++) {
cin >> mat[r][c];
if (mat[r][c] > mat[r][c - 1])
sum += mat[r][c] - mat[r][c - 1];
}
ans += sum;
}
for (int c = 1; c <= col; c++) {
int sum = 0;
for (int r = 1; r <= row; r++) {
if (mat[r][c] > mat[r - 1][c])
sum += mat[r][c] - mat[r - 1][c];
}
ans += sum;
}
cout << 2 * ans << "\n";
return 0;
}