PS

BOJ 11982 : Angry Cows (Gold)

lsj_haru 2024. 2. 8. 14:18

알고리즘

dp, two_pointer

시간복잡도

$O(NlogN)$

풀이

현재 점 왼쪽의 모든 점을 연쇄적으로 터뜨릴 수 있는 최솟값을 $dpl[i]$,
마찬가지로 오른쪽의 경우 $dpr[j]$로 구한다.

 

임의의 두 점에 대하여 두 점 사이 거리의 절반,
앞에서 구한 $dpl, dpr$ 값들 중 최댓값이 전체 최솟값 후보일 것이다.
이를 $O(N^2)$로 구하면 시간초과가 나기에
맨 끝에서부터 two pointer로 관리해주면 된다.
(dp값이 작은 것을 밀도록)

코드

#include <bits/stdc++.h>
using namespace std;

int N, a[50005], dpl[50005], dpr[50005];
int ans = 2e9;

int main()
{
    cin>>N; for (int i = 1; i <= N; i++) {cin>>a[i]; a[i]*=2;}
    sort(a+1, a+N+1);
    dpl[1] = dpr[N] = -2;
    dpl[2] = a[2] - a[1]; dpr[N-1] = a[N] - a[N-1];
    int len = 0, now = dpl[2] + 2;
    for (int i = 3; i <= N; i++) {
        len += a[i] - a[i-1];
        if (len <= now) {dpl[i] = now; continue;}
        dpl[i] = max(dpl[i-1] + 2, a[i] - a[i-1]);
        now = dpl[i]; len = a[i] - a[i-1];
    }
    len = 0; now = dpr[N-2] + 2;
    for (int i = N-2; i >= 0; i--) {
        len += a[i+1] - a[i];
        if (len <= now) {dpr[i] = now; continue;}
        dpr[i] = max(dpr[i+1] + 2, a[i+1] - a[i]);
        now = dpr[i]; len = a[i+1] - a[i];
    }
    int i = 1, j = N;
    while (i < j)
    {
        ans = min(ans, max((a[j]-a[i])/2, max(dpl[i]+2, dpr[j]+2)));
        dpl[i+1] < dpr[j-1] ? i++ : j--;
    }
    if (ans%2) cout<<ans/2<<".5";
    else cout<<ans/2<<".0";
    return 0;
}

'PS' 카테고리의 다른 글

BOJ 28327 : 지그재그  (2) 2024.02.20
BOJ 12011 : Splitting the Field  (0) 2024.02.11
BOJ 11993 : Circular Barn (Gold)  (0) 2024.02.08
BOJ 3847 : Comparing answers  (2) 2024.02.08
BOJ 2272 : 램프  (0) 2024.02.08