티스토리 뷰

http://oj.uz/problems/view/balkan11_timeismoney

처음에 이러한 문제를 딱 보고 생각이 난건, 한쪽의 sum을 고정시키고 진행하는 knapsack 류의 방법인데 (다익스트라가 그렇게 되니까) 해보면 알겠지만 Prim / Kruskal에서 그런 짓을 하는 거랑 다익스트라에서 하는 거랑은 느낌이 많이 다르다 (ㅜㅜ).

정점 V, 간선 E, max(t, c) = M = 255라고 하겠다.


O(ElgE * (VM)^2) / O(V^4M^2)

중요한 고찰이 필요하다. 나올 수 있는 모든 MST의 경우의 수를 (Sigma(T), Sigma(C)) 좌표 형태로 좌표평면에 찍었을 때, xy를 최소화하는 점을 골라야 한다. 최소인 점을 찾았다 치고, 그 점에서 y = T/x의 도함수 값을 y'라 할 때, 이 점은 y + y'x 역시 최소화한다. 이게 무슨말이냐 하면 모든 실수범위에서의 도함수의 경우를 나열하고 cost 함수를 저런 식으로 써서 MST를 구하면 된다는 거다. 실수를 전탐색한다는 게 참 웃기지만 뭐 일단 이렇게 하면 답은 나온다.. 그건 확실.

이제 답의 후보를 줄이자. 결론부터 말하면 답은 a / b 꼴이며 이 때 a, b <= VM이다. 이것의 증명은 자명해보이지.. 않다. 이제 이 경우들을 다 시도해서 MST를 구하면 됨.


O(ElgEVM) / O(V^3M)

결국 답의 후보를 줄이는 게 과제인데, 위에서 좌표 형태로 MST를 플롯했기 때문에 모든 좌표의 컨벡스 헐을 구하고 그 안에서 뒤지면 될 것 같다는 직감을 받을 수 있다. 컨벡스 헐의 크기는 O(VM)일 테니까 이제 이걸 할 수만 있다면 완벽하다. 물론 좌표의 크기가 지수적이니.. 여기서 아주 이상한 재귀적 방법을 사용한다.

먼저, t만을 최적화한 점과 c만을 최적화한 점을 구한 후, 이 두점을 s, e라 하고 재귀함수를 돌리자. 두 점을 잇는 일차함수를 최적화하는 점인 m을 O(ElgE)에 찾을 수 있고, 만약 그 점이 컨벡스 헐 안에 들어가면 [s, m] / [m, e]에서 또 계속 돌리자 계속.. 이렇게 하면 O(VM)개의 컨벡스 헐 후보를 모두 구할 수 있다. 유의미한 후보 중 구해지지 않는 후보는 없다.

실제로는 후보가 오더보다 많이 적어서 적은 것보다 훨씬 빨리 돌고 무튼 이렇게 하면 AC가 뜬다. 위에서 요구했던 증명은.. 컨벡스 헐 상에서 양 옆으로 인접한 두 점의 기울기를 생각해 보자.


사실 이 문제는 말로 하는 것 보다 코드가 더 나을 것 같다.. https://github.com/koosaga/olympiad/blob/master/Balkan/balkan11_timeismoney.cpp

또한 공식 풀이에 visualization이 아주 잘 되어 있으니 그것도 참고 http://www.boi2011.ro/resurse/tasks/timeismoney-sol.pdf


첨언

대회 때 이런 문제가 나왔고 데이터가 적당히 약해보인다면 simulated annealing을 시도하는 것도 나쁘지 않아 보인다.

여담으로 pseudopolynomial이니 아마 실제로는 np일거 같다.

'공부 > Problem solving' 카테고리의 다른 글

거울대칭트리 그래프 (BOJ 2430. BOI 2011)  (0) 2016.01.03
some problem solving 2016.01  (0) 2016.01.03
케이크 (JOI Spring Camp 2013)  (0) 2015.12.27
미술관 (KOI 2015 중등부 4번)  (0) 2015.12.14
Toys (USACO Nov 08 Gold)  (0) 2015.12.13
댓글
공지사항
최근에 올라온 글
Total
Today
Yesterday