BOJ 1150 - 백업

image.png

거의 하루동안 끈기있게 고민한 문제이다. 44번 째 풀이를 고안하다 맞았는데, 풀이과정을 접어서 보관해두긴 하겠다.

문제 지문은 단순하다.

일단 케이블을 이은 두 쌍 (a,c)(a,c)(b,d)(b,d)의 거리를 봤을 때 a<b<c<da < b < c < d라면 (a,b)(c,d)(a,b) (c,d)로 바꿔주는게 항상 최적이므로 kk개의 케이블은 모두 인접한 도시에만 사용해줘야한다.

Trial 1 - DPPermalink

뭔가 DP같으니 먼저 DP로 시도해보도록 하겠다.

dp[p][i]=idp[p][i]=i번째 회사까지 봤을 때, ii번째 회사는 항상 쌍에 오른쪽으로 포함되고 pp개의 쌍을 지어줬을 때의 최소값이라고 하자.

점화식을 세워보자.

x(i)x(i)ii의 위치라고 하자.

dp[p][i]={if  p>i/2  or  p=0  or  i0Minj=0i2  dp[p1][j]+x(i)x(i1)otherwise dp[p][i]=\begin{cases} \infty&\text{if}~~p>\left\lfloor i/2 \right\rfloor~~\text{or}~~ p=0 ~~\text{or}~~ i \le 0\\ Min_{j=0}^{i-2} ~~ dp[p-1][j]+x(i)-x(i-1) &\text{otherwise} \end{cases}

00-based 인덱스이다.

O(n2)O(n^2) 짜리 점화식이 나왔는데, 이 문제가 그리디문제가 아니라면 DP최적화 기법을 사용해야 되는 문제같다.

뭔가 분할정복최적화 같아서 이전에 공부했던 내용을 살펴보았다.

아닌가?

DnC opt의 조건을 보니 최적해에 단조성만 있으면 된다.

위 점화식에서 opt[p][i]opt[p][i]dp[p1][j]dp[p-1][j]가 최소가 될 때의 jj라고 하자.

opt[p][i]opt[p][i+1]opt[p][i] \le opt[p][i+1] 인가? \Rightarrow 그렇다.

왜냐면 i+1i+1ii를 항상 이어주어야 해서 실제 DP값은 단조성이 없지만, 최적해로 고를 수 있는 jj의 범위는 더 오른쪽으로 선택권이 넓어졌기 때문에 이전에 골랐던 jj를 항상 골라줄 수 있기 때문이다.

따라서 구현 어떻게 하는지 기억도 잘 안나는(빨리 이 블로그에도 정리해야겠다) DnC를 구현법을 참고해서 구현하면 될 것 같다.

아 쉬바 구현하다 뭔가 이상해서 살펴보니 DnC opt의 시간복잡도는 O(KNlgN)O(KNlg N)이였다.

Trial 2 - GreedyPermalink

우리가 이어주어야 할 쌍은 KK쌍이다.

그런데 하나의 쌍을 이을 때, 우린 총 N1N-1개의 구간 중, 22혹은 33개의 구간을 못쓰게된다.

정확히 말하면 모든 구간의 길이의 합은 x(N1)x(0)x(N-1)-x(0)인데, iii+1i+1를 이었다고 하면,

x(i+1)x(i)x(i+1)-x(i)는 구간의 길이(정답)에 더해지고,

x(i)x(i1)x(i)-x(i-1)x(i+2)x(i+1)x(i+2)-x(i+1)은 전체 구간의 길이에서 빼진다고 생각할 수 있다.

그럼 이걸 최대한 많이 빼면 정답아닐까?

근데 항상 원하는 구간만 모두 사용할 수 있을까?

1kn/21 \le k \le \left\lfloor n/2 \right\rfloor 이다.

다음과 같이 가장 worst case로 이엇다고 해보자.

X는 이어지지 않은 도시이고 O는 이어진 도시이다.

X O - O X O - O X O - O X ...

NN에 대해 KK가 얼마나 적어야 저렇게 이을 수 있는지 보자.

N K
3 1
4 1

벌써 망했다. N=4N=4라면 K=2K=2 까지 입력에서 들어올 수 있는데, 저딴식으로 이어버리면 안되기 때문이다.

연속된 NN개의 도시는 최대 N/2\left\lfloor N/2 \right\rfloor개의 KK를 소모할 수 있다.

여기까지 생각하고 태그를 깠다.Permalink

여기까지의 추론이 틀린것은 아니였고 예상대로 Greedy + Priority Queue 였다.

이제 밥을 먹고 다시 생각해보겠다.


전체 구간에서 양옆 두 구간의 합이 더 긴것부터 제거해나갈 수 있는걸 이어나가는게 최적이라는 가설을 세웠다.

어떤걸 제거해갈 때 항상 남은 도시들로 소모할 수 있는 KK가 몇개인지 관리할 수 있을까?

O --5-- O --5-- O --5-- O

처럼 되어있을 때, N=4,K=2N=4,K=2인데 어떻게 중간걸 안고르고 왼쪽이나 오른쪽을 골라야한다 라고 판단을 할 수 있을까?

이것도 아닌듯

Trial 3Permalink

어떤걸 먼저 정렬해서 볼 생각을 하지 말고, 왼쪽부터 KK개의 쌍을 먼저 짝지어준 다음, i=2Ki=2K 부터 시작해서 이전에 했던 선택과 교체해주도록 시도해보자.

이런식의 진행은 Greedy + PQ에서 흔한 패턴인데, 이런 문제를 너무 접한지 오래되어서 까먹었었다.

N=5,K=2N=5, K=2 라고 하자.

X - X X - X O

이고 다섯 번째껄 보고있는데,

X - X O  X - X

처럼 하나만 스왑해준다고 하자. 그런데 01\overline{01}말고 12\overline{12}을 선택할 수 있게 되었고 이게 최적일 수도 있는데, 한 번의 인덱스당 하나의 교체만 진행한다면 뭔가 완전하지 않다.

무언가 연쇄적으로 연산을 적용시켜줘야 할 것 같다.

O -100- O -1- O -100- O -150- O

우선 작은걸 최대한 모두 이어준 다음, 남은 쌍 개수를 TT라고 하자.

N=13,K=6N=13, K=6 라 하자. 최대로 TT가 많이 남았을 때, 다음처럼 T=2T=2 이다.

O [O O] O [O O] O [O O] O [O O] O

이제 무조건 연결되어있는 것 중 하나를 끊어야한다.

첫 번째껄 끊는다고 해보자. 양 옆 두개중에 하나에 붙여줄 수 있다.

(1) [O O] O O [O O] O [O O] O [O O] O
(2) O O [O O] [O O] O [O O] O [O O] O

즉, [i,i+1][i, i+1]를 끊는다고 할 때, 이것으로 인해 보는 손실(정답에 늘어나는 값)은 (xi+1xi)+Min(xixi1,xi+2xi+1)-(x_{i+1}-x_i)+Min(x_i-x_{i-1}, x_{i+2}-x_{i+1}) 이다.

이걸 우선순위큐로 관리하며 제일 손실이 없는것부터 끊어준다고 해보자.

저렇게 초기 상태에선 어떤걸 끊어서 좌우로 한 칸 밖에 못움직였지만, 하나를 끊어주고나니 그냥 바로 이어줄 수 있는 것도 생기고 그렇다.

그런데 어떤 NN에 대해 최대로 생길 수 있는 TT는 얼마일까? TKT \le K 일텐데 말이다.

한번 표로 생각해보자.

NN Max KK TT
3 1 0
4 2 1
5 2  

아닌듯 작은걸 최대로 이어준다는 것부터가 불가능


Trial 4 (AC)Permalink

사용하지 않은 도시는 0, 사용한 도시는 1로 생각한다.

처음에 모든 도시가 사용을 안하므로

0 0 0 0 0 0 0 0 0 ..

이다.

무조건 한 쌍을 이어주며 얻을 수 있는 가장 작은 길이를 우선순위큐로 관리해보자.

처음엔 N1N-1개의 구간에 대해 모두 우선순위 큐에 넣어둔다.

가장 비용이 적은 도시를 고른다.

0 0 0 0 1 - 1 0 0 0 ..

항상 어떤 0 사이엔 짝수개(00포함)의 11이 있어야 한다.

그런데, 1 11~1 양 옆의 0 00~0을 보자.

이 두개를 이어주기 위해선 그 사이의 연결된 도시들의 연결 방향을 모두 뒤집은다음

0 0 0 1 - 1 1 - 1 0 0 ..

처럼 이어줄 수 있다.

그리고 정확히 우린 한 개의 연결을 추가했다.

이렇게 특정 구간을 반전시켰을 때 증가하게 되는 값은 구간합배열을 전처리해두면 O(1)O(1)에 구해줄 수 있다.

이제 우선순위큐를 쭉 돌리면서 특정 구간을 반전시켜서 얻는 값을 우선순위큐에 넣어버린다.

pop 했는데 벌써 사용하지 못하게 된 0 두개라면 skip한다.

그런데 항상 두 00 바로 왼쪽 오른쪽이 그 다음 00인 구간이라는 보장은 없으므로 이건 적절한 자료구조 아무거나 사용해서 그 다음 00 두 개를 O(logN)O(\log N) 정도에 찾아주자.

본인은 세그먼트 트리와 이분탐색으로 구현했지만 시간복잡도는 문제없다.

이런식으로 쭉 돌리면 정답이다.

이것이 최적인 이유는 Flow와 연관지어 augmenting path를 찾는 방법으로 생각하면 증명이 된다고 한다.

Tags:

Categories:

Updated:

Comments