문제 풀이

[BOJ] 1451 | 직사각형으로 나누기

문제

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

풀이

01

가능한 6가지 경우의 수를 생각하여 모든 경우의 수를 계산해주면 된다.

직사각형의 넓이를 구할때는 구간 합(prefix sum)을 이용하여 O(1)에 계산해줄 수 있다.

두 직사각형 사이에 한 직사각형이 껴있는 경우의 시간복잡도는 각각 O(N^2)과 O(M^2),

나머지 경우의 수는 시간복잡도가 O(NM)이므로, 대충 전체 시간복잡도는 O(NM).

소스

#include<iostream>
#include<algorithm>
using namespace std;

long long N, M, arr[111][111], sum[111][111], ans;

int main() {
	scanf("%d%d", &N, &M);
	for (int i = 1; i <= N; i++)
		for (int j = 1; j <= M; j++) {
			scanf("%1d", &arr[i][j]);
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + arr[i][j];
		}
	for (int i = 1; i < N; i++)
		for (int j = 1; j < M; j++) {
			long long a, b, c;
			a = sum[i][j];
			b = sum[N][j] - sum[i][j];
			c = sum[N][M] - sum[N][j];
			ans = max(ans, a*b*c);

			b = sum[i][M] - sum[i][j];
			c = sum[N][M] - sum[i][M];
			ans = max(ans, a*b*c);

			a = sum[N][M] - sum[N][j] - sum[i][M] +sum[i][j];
			b = sum[N][j];
			c = sum[i][M] - sum[i][j];
			ans = max(ans, a*b*c);

			b = sum[i][M];
			c = sum[N][j] - sum[i][j];
			ans = max(ans, a*b*c);
		}
	for (int i = 1; i < N; i++)
		for (int j = i + 1; j < N; j++)
			ans = max(ans, sum[i][M] * (sum[j][M] - sum[i][M]) *(sum[N][M] - sum[j][M]));
	for (int i = 1; i < M; i++)
		for (int j = i + 1; j < M; j++)
			ans = max(ans, sum[N][i] * (sum[N][j] - sum[N][i]) *(sum[N][M] - sum[N][j]));
	cout << ans;
}
← 문제 풀이 글 더 보기