Skip to content

Commit 5c91673

Browse files
committed
히스토그램
1 parent 4a8d590 commit 5c91673

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

challenges/BOJ1725.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 문제
2+
히스토그램
3+
## 문제 원본
4+
문제의 원본은 [여기서](https://www.acmicpc.net/problem/1725) 확인하세요.
5+
6+
## 분류
7+
* 분할 정복
8+
9+
# 풀이
10+
11+
히스토그램을 절반씩 나누어 분할 정복 한다. 이때 넓이의 최대값이 되는 경우는 아래와 같다.
12+
13+
넓이가 가장 큰 직사각형이
14+
15+
1. 왼쪽 부분에 있는 경우
16+
2. 중간에 걸쳐 있는 경우
17+
3. 오른쪽 부분에 있는 경우
18+
19+
1번과 2번은 재귀함수를 통해 구현하고 3번의 경우는 중간에서 좌우로 확장해 나가며 넓이를 구한다. 이렇게 구해진 3개의 넓이중에서 최대 넓이가 그 부분문제에 있어 최대 직사각형 넓이가 된다.
20+
21+
``` c++
22+
#include <iostream>
23+
24+
using namespace std;
25+
26+
int h[100000]; // 높이
27+
28+
int histo(int left, int right) {
29+
// 한칸인 경우 넓이는 높이와 같다. (가로 = 1)
30+
if (left == right) return h[left];
31+
32+
// 중간을 구한다.
33+
int mid = (left + right) / 2;
34+
// 구해준 중간을 기준으로 좌우의 넓이중 더 큰수를 구한다.
35+
int ans = max(histo(left, mid), histo(mid + 1, right));
36+
37+
int low = mid;
38+
int high = mid + 1;
39+
40+
// 중간을 기준으로 양쪽에 높이가 더 작은 막대를 찾는다.
41+
int height = min(h[low], h[high]);
42+
43+
// 좌우중 더 넓은 넓이와 중간의 넓이와 비교하여 큰값으로 바꾼다.
44+
ans = max(ans, height * 2);
45+
46+
// 중간을 기준으로 왼쪽과 오른쪽으로 확장
47+
while (left < low || high < right) {
48+
if (high < right && ((low == left) || h[low - 1] < h[high + 1])) {
49+
high++;
50+
height = min(height, h[high]);
51+
}
52+
else {
53+
low--;
54+
height = min(height, h[low]);
55+
}
56+
57+
// 기존 최대 넓이와 중간에서 확장된 넓이와 비교 후 업데이트
58+
ans = max(ans, height * (high - low + 1));
59+
}
60+
61+
return ans;
62+
}
63+
64+
int main(void) {
65+
ios::sync_with_stdio(false);
66+
cin.tie(0); cout.tie(0);
67+
68+
int n;
69+
cin >> n;
70+
71+
for (int i = 0; i < n; i++) {
72+
cin >> h[i];
73+
}
74+
75+
cout << histo(0, n - 1) << "\n";
76+
return 0;
77+
}
78+
```

0 commit comments

Comments
 (0)