티스토리 뷰

Algorithm/ALGOSPOT

FENCE

henry1214 2021. 6. 7. 18:27

https://algospot.com/judge/problem/read/FENCE

 

algospot.com :: FENCE

울타리 잘라내기 문제 정보 문제 너비가 같은 N개의 나무 판자를 붙여 세운 울타리가 있습니다. 시간이 지남에 따라 판자들이 부러지거나 망가져 높이가 다 달라진 관계로 울타리를 통째로 교체

algospot.com

 

각각의 높이가 다른 울타리에서 최대 넓이의 직사각형을 찾는 문제이다. 여러 방법으로 풀 수 있지만 여기서는 분할 정복으로 풀어보도록 하자. 전체 판자를 절반으로 나눈다고 하자. 그러면 우리가 찾는 최대 직사각형은 다음 세 가지 중 하나에 속한다.

 

1. 가장 큰 직사각형을 왼쪽 부분 문제에서만 잘라낼 수 있다.

2. 가장 큰 직사각형을 오른쪽 부분 문제에서만 잘라낼 수 있다.

3. 가장 큰 직사각형이 왼쪽 부분 문제와 오른쪽 부분 문제에 걸쳐져 있다.

 

1,2번은 전체 문제를 반으로 나눈 부분 문제를 재귀 호출하여 해결할 수 있다. 3번의 경우만 고려하면 된다. 먼저 3번의 경우 분할한 기준으로부터 인접한 왼쪽, 오른쪽 판자는 무조건 포함한다는 것을 알 수 있다. 그리고 양 옆을 비교해서 높이가 더 높은 판자쪽으로 확장해가면서 넓이를 갱신해주면 된다.

 

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

int h[20005];

int solve(int left,int right)
{
    if(left==right) return h[left];
    int mid=(left+right)/2;
    int ret=max(solve(left,mid),solve(mid+1,right));
    int low=mid,high=mid+1;
    int height=min(h[low],h[high]);
    ret=max(ret,height*2);
    while(left<low || high<right)
    {
        if(high<right && (low==left || h[low-1]<h[high+1]))
            height=min(height,h[++high]);
        else
            height=min(height,h[--low]);
        ret=max(ret,height*(high-low+1));
    }
    return ret;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&h[i]);
        printf("%d\n",solve(0,n-1));
    }
    return 0;
}

'Algorithm > ALGOSPOT' 카테고리의 다른 글

WILDCARD  (0) 2021.06.20
JUMPGAME  (0) 2021.06.13
QUADTREE  (0) 2021.06.07
CLOCKSYNC  (0) 2021.06.07
BOARDCOVER  (0) 2021.06.07
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday