:: ADVANCE ::
[BaekJoon][1915] 가장 큰 정사각형 본문
BAEKJOON ONLINE JUDGE
https://www.acmicpc.net/problem/1915
DP!!
풀이 1. 수학 + 구현
1000x1000 이므로 일단 input을 한번씩 탐색하는 것은 가능하다.
but, 탐색하면서 정사각형인지를 판단할 때 배열을 다시 탐색하는 일은 아마도 Time Limit이 발생할 것이다.
따라서, 정사각형인지를 판단하는 여부를 줄였다.
정사각형의 면적은 한 변의 제곱이다.
또한 입력은 0아니면 1이기 때문에 배열에 해당하는 값의 합(면적)이 한 변의 제곱과 같으면
정사각형이라고 판단하였다.
0 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
위 입력에서 표시한 지점의 입력의 합 4이며 변이 2인 정사각형의 면적과 같다.
면적을 구할 때 또한 반복문을 통해 일일이 계산을 하면 탐색이 중복된다.
따라서 효율적으로 합을 구하는 방법은
sum[i][j] 배열을 이용하는 것.
sum[i][j] 배열은 (0, 0)부터, (i, j)에 해당한는 지점까지의 합을 뜻한다.
0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 1 | 1 | 0 |
0 | 0 | 1 | 0 |
예를 들어 위 입력에서 sum[2][1] = 4로 노란 지점의 합이다.
1 2 3 4 5 6 | for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { scanf("%1d", &map[i][j]); sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + map[i][j]; } } | cs |
이렇게 각 지점의 (0, 0)부터의 면적을 구한 후
원하는 지점의 면적은
space = sum[y][x] - sum[y][j] - sum[i][x] + sum[i][j];
식으로 구할 수 있다.
0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 1 | 1 | 0 |
0 | 0 | 1 | 0 |
즉, 위 예제에서 하늘색에 해당하는 면적은 색이 칠해진 전체에서 노란색 부분을 빼고, 빨간색 부분을 빼고, 주황색 부분은 노란색과 빨간색을 빼줄 때 겹치는 부분으로 중복되어 빼지기 때문에 다시 더해주면 구할 수 있다.
따라서 면적을 구하는 방법은 반복문이 아닌 하나의 식으로 대체할 수 있다.
다음 단계로, 가장 큰 정사각형을 구해야 하기 때문에 한 지점 (y, x)를 정사각형의 왼쪽 위 좌표로 하였을 때
변수 length을 두어 그만큼의 sum과 길이 제곱을 통한 면적의 비교로 정사각형의 여부를 판단하고,
정사각형일 때 length++을 하여 더 큰 정사각형인지를 찾았다.
그 다음 (y, x)를 시작으로 길이 length인 정사각형의 최대치를 찾은 후에는
y, x를 탐색해 가며 length보다 긴 길이를 가진 정사각형을 탐색한다.
설명이 장황하여 어렵지만... 어렵게 푼거 같다...
0 | 1 | 0 | 0 |
1 | 1 | 1 | 1 |
0 | 1 | 2 | 2 |
0 | 1 | 2 | 3 |
같은 경우 dp[][]의 값인데, i = 0인 지점과 j = 0인 지점은 input과 같다.
그 이유는 위쪽과 왼쪽을 바라 볼 수 없기 때문에 입력과 같은 것이다.
(입력의 1과 달리 dp의 1은 정사각형 변의 길이 1을 의미)
'Algorithm > DP (동적계획법)' 카테고리의 다른 글
[BaekJoon][2531] 회전 초밥 (0) | 2016.06.25 |
---|---|
[BaekJoon][7579] 앱 (0) | 2016.06.25 |
[BaekJoon][9095] 1, 2, 3 더하기 (0) | 2016.04.11 |
[BaekJoon][1149] RGB거리 (0) | 2016.04.11 |
[dovelet][DP] SCV 자원채취 / SCV (0) | 2015.01.07 |