티스토리 뷰
N개의 수들이 주어지고, 이 N개의 수들을 2개로 그룹지어서 2개의 그룹의 곱이 최대가 되도록 만들면 된다. (그룹의 가중치 = 그룹에 속한 수들의 합)
N=10만이므로, N^2 풀이는 당연히 불가능하다.
우선 테스트케이스에서 99가 나오는 원리이다. 1,2,3 번째에서 -11, 5번째에서 -9를 선택하면 곱이 99가 되고, 이 값이 최대이다.
l_max[],l_min[]배열은 왼쪽부터 보면서 누적합을 계산해 나간다. 여기서 max[]배열은 양수만 고려하므로 만약 누적합이 0보다 작아진다면 차라리 그 수를 선택하지 않는것이 더 나은 선택이므로 0이 된다. min[]배열 또한 같은 원리로 누적합이 0보다 커진다면 그냥 0으로 둔다. 그리고 maxS는 이러한 max 배열들 중에서 지금까지의 가장 큰 값을 저장하는 배열이다. 여기서 색깔이 입혀진 이유는 아래에 곧 나온다.
같은 원리로 r배열은 오른쪽에서부터 왼쪽까지 배열을 채워넣는다.
이제 l배열과 r배열에서 노란색으로 칠해진 칸을 볼 것이다. 왼쪽부터 한칸씩 보면서 빨간색 막대를 기준으로 l_max[]배열은 작대기 왼쪽에서 가장 큰 값, 작대기 오른쪽에서는 r_maxS[]배열에서 가장 큰 값을 찾아서 곱해간다.
이제 max배열(양수)과정이 끝나고 이번에는 min배열(음수)을 볼 것이다. 방법은 방금과 같다.
이렇게 되면 (음수)*(음수)인 99가 최종 답이 된다.
이 풀이가 가능한 이유는 l_max배열은 왼쪽에서부터 누적합이 가장 큰 그룹의 가중치를 저장하고, r_maxS배열은 오른쪽에서부터 누적합이 가장 큰 그룹의 가중치를 저장하므로 특정 경계선(위 그림에선 빨간색 막대)를 정하고 그 경계의 양쪽에서의 값을 서로 곱하면 결과적으로 왼쪽에서의 가중치와 오른쪽에서의 가중치의 곱의 최대를 구한게 된다.
사소한 예외처리로는, N=2일때는 답이 반드시 (첫번째 값) * (두번째 값) 이 되도록 처리해주어야 한다. 그렇지 않으면 위에서 max[],min[] 배열들의 값을 채울 때, 값이 0이 넘어가느냐 마느냐에 따라서 임의로 0으로 채워주었으므로 답이 0이 나올수도 있다. 예를 들어
2
-3 3
이라는 데이터는 반드시 -9가 나와야 한다.
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 | #include<stdio.h> #include<algorithm> using namespace std; typedef pair<int,int> pii; typedef long long ll; #define SIZE 1000009 int l_max[SIZE],r_max[SIZE],l_min[SIZE],r_min[SIZE],arr[SIZE]; int l_maxS[SIZE],r_maxS[SIZE],l_minS[SIZE],r_minS[SIZE]; int main(){ int n; scanf("%d",&n); for(int i=1 ; i<=n ; i++){ scanf("%d",&arr[i]); } for(int i=1 ; i<=n ; i++){ l_max[i]=max(0,l_max[i-1]+arr[i]); l_maxS[i]=max(l_maxS[i-1],l_max[i]); l_min[i]=min(0,l_min[i-1]+arr[i]); l_minS[i]=min(l_minS[i-1],l_min[i]); } for(int i=n ; i>=1 ; i--){ r_max[i]=max(0,r_max[i+1]+arr[i]); r_maxS[i]=max(r_maxS[i+1],r_max[i]); r_min[i]=min(0,r_min[i+1]+arr[i]); r_minS[i]=min(r_minS[i+1],r_min[i]); } ll ans=0; if(n==2) ans=(ll)arr[1]*arr[2]; for(int i=1 ; i<=n && n!=2; i++){ ans=max(ans,(ll)l_max[i]*r_maxS[i+1]); ans=max(ans,(ll)l_min[i]*r_minS[i+1]); } printf("%lld\n",ans); return 0; } | cs |
'Problem Solving > Dynamic Programming' 카테고리의 다른 글
[BOJ 2662]기업투자 (0) | 2019.01.16 |
---|---|
[BOJ]13302-리조트 (0) | 2019.01.15 |
2624-동전 바꿔주기 (0) | 2018.12.03 |
12865-평범한 배낭 (0) | 2018.12.03 |
2294-동전2 (0) | 2018.12.03 |