BOJ

백준 2104 - 부분배열 고르기

yanJuicy 2019. 6. 8. 14:19
반응형

문제

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

 

2104번: 부분배열 고르기

문제 크기가 N(1≤N≤100,000)인 1차원 배열 A[1], …, A[N]이 있다. 어떤 i, j(1≤i≤j≤N)에 대한 점수는, (A[i]+…+A[j])×Min{A[i], …, A[j]}가 된다. 즉, i부터 j까지의 합에다가 i부터 j까지의 최솟값을 곱한 것이 점수가 된다. 배열이 주어졌을 때, 최대의 점수를 갖는 부분배열을 골라내는 프로그램을 작성하시오. 입력 첫째 줄에 정수 N이 주어진다. 다음 줄에는 A[1], …, A[N]을 나타내는 정수들

www.acmicpc.net

 

풀이

이유 : 가운데를 걸치는 부분배열에서 최대값을 구할 때 시간초과가 났다.

 

최대 부분 배열을 고르는 알고리즘은 분할 정복을 이용한다.

가운데를 기준으로 1.왼쪽 부분 배열 2.오른쪽 부분 배열 3.가운데에 걸치는 부분 배열 총 3가지 경우가 나온다. 이 세가지 중 가장 큰 값을 반환하는 부분 배열이 답이 된다.

가운데 걸치는 부분 배열을 구할 때는 배열에 중간에서 시작해서 왼쪽 또는 오른쪽으로 1칸씩 확장해 나가야 한다. 이 때 왼쪽, 오른쪽 중 큰 쪽으로 확장을 해야한다. 1칸씩 확장해 나가면서 현재까지의 최대값과 비교한다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int MAX = 1000001;
 
int N;
int A[MAX];
 
long long GetMax(int from, int to)
{
    // 기저 사례
    if (from == to) return (long long)A[from] * A[from];
 
    int mid = (from + to) / 2;
    long long leftSum = GetMax(from, mid);
    long long rightSum = GetMax(mid + 1, to);
 
    // 왼쪽, 오른쪽 부분배열 중 최대를 찾음
    long long maxValue = max(leftSum, rightSum);
 
    int left = mid;
    int right = mid + 1;
 
    // mid에서 시작하는 교차하는 부분 배열
    long long sum = A[left] + A[right];
    long long minValue = min(A[left], A[right]);
    // 최대 값 비교
    maxValue = max(maxValue, sum * minValue);
 
    // 교차 하는 부분 배열에서 최대를 찾음
    while (left > from || right < to)
    {
        // 오른쪽으로 증가
        if (right < to && (left == from || A[left - 1< A[right + 1]))
        {
            sum += A[++right];
            minValue = min(minValue, (long long)A[right]);
        }
        else    // 왼쪽으로 증가
        {
            sum += A[--left];
            minValue = min(minValue, (long long)A[left]);
        }
        long long crossSum = sum * minValue;
        // 최대 값 비교
        maxValue = max(maxValue, crossSum);
    }
    
    return maxValue;
}
 
int main() 
{
    cin.tie(0);
    ios::sync_with_stdio(false);
 
    cin >> N;
    for (int i = 1; i <= N; i++cin >> A[i];
 
    cout << GetMax(1, N);
 
    return 0;
}
cs

 

반응형

'BOJ' 카테고리의 다른 글

백준 1935 - 후위표기식2  (0) 2019.06.11
백준 1918 - 후위표기식  (0) 2019.06.10
백준 1904 - 01타일  (0) 2019.06.05
백준 1700 - 멀티탭 스케줄링  (0) 2019.06.03
백준 2503 - 숫자 야구  (0) 2019.06.01