페이지

3357번: Monument

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


$O(pqr)$

다음 두 문제의 아이디어를 조합하면 풀 수 있다.
(1) http://codedoc.tistory.com/723
(2) http://codedoc.tistory.com/911

(x,y,z)상에 0 혹은 1이 주어졌을 때 1로만 이루어진 a*a*b꼴 직육면체 중 최대 4ab를 구해보자.
편의상 xy평면과 직육면체의 정사각형인 밑면과 평행하다고 하자.
푼 다음 직육면체를 적절히 돌려 나머지 방향에서도 똑같이 풀면 될 것이다.
먼저, 각 (x,y,z)마다 해당 지점을 끝점으로 하는 (1...x,1...y,z)상의 가장 큰 정사각형 한 변 길이를 구해놓는다. ... (2)
(x,y,1...i...z)에서 (x,y,i)의 최대 정사각형 한 변 길이를 a[i]라 하고 이들로 이루어진 히스토그램상에서 최대 직사각형 넓이를 구한다. ... (1)
이렇게 하면 (x,y,1...z)가 직육면체의 끝점이 되는 (1...x,1...y,1...z) 상의 직육면체 최대 ab가 구해진다.
모든 x,y에 대해 똑같이 풀고 최대 4ab를 구한다.


#include<cstdio>
#include<algorithm>
using namespace std;
int a[3], p[3] = { 0,1,2 }, pi[3], c[3], dp[151][151][151], stk[151], top, r;
char s[151][151][152];
int main() {
    scanf("%d%d%d", a + 1, a, a + 2);
    for (int i = 1; i <= a[0]; i++) for (int j = 1; j <= a[1]; j++) scanf("%s", s[i][j] + 1);
    do {
        for (int i = 0; i < 3; i++) pi[p[i]] = i;
        for (int i = 1; i <= a[p[0]]; i++) {
            for (int j = 1; j <= a[p[1]]; j++) {
                for (int k = 1; k <= a[p[2]]; k++) {
                    c[pi[0]] = i; c[pi[1]] = j; c[pi[2]] = k;
                    int n = s[c[0]][c[1]][c[2]] == 'N';
                    dp[i][j][k] = (min({ dp[i - 1][j][k], dp[i][j - 1][k], dp[i - 1][j - 1][k] }) + 1)*n;
                    while (dp[i][j][stk[top]]>dp[i][j][k]) r = max(r, (k - 1 - stk[top - 1])*dp[i][j][stk[top--]]);
                    stk[++top] = k;
                }
                while (top) r = max(r, (a[p[2]] - stk[top - 1])*dp[i][j][stk[top--]]);
            }
        }
    } while (next_permutation(p, p + 3));
    printf("%d", 4 * r);
    return 0;
}

댓글 없음 :

댓글 쓰기