Top Banner
정원 분할 (IOI 2005) 구재현 (gs14004)
25

IOI 2005 정원 분할 (2015.03.05)

Aug 08, 2015

Download

Software

Jaehyun Koo
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: IOI 2005 정원 분할 (2015.03.05)

정원 분할 (IOI 2005)구재현 (gs14004)

Page 2: IOI 2005 정원 분할 (2015.03.05)

Problem

• K개의 장미를 포함하는 직사각형 2개를 선택해야 한다

• 둘레의 합을 최소화하는 방향으로 두 직사각형을 고르는 방법은?

• W, L <= 250 (이후 편의상 W = L = N으로 정의)

• 현재 IOI 기준에서는 쉬운 편^^;;

Page 3: IOI 2005 정원 분할 (2015.03.05)

Naive Algorithm Design

• 이 문제의 답이 될 수 있는 모든 경우를 고민해 보자

• 두 직사각형을 고른다 -> 네개의 점을 고른다 -> O((N^2)^4) = O(N^8) 가지 경우

• 두 직사각형을 고르고, 이것이 K개의 장미를 가졌는지 검사하는데 드는 시간은 O(N^2)

Page 4: IOI 2005 정원 분할 (2015.03.05)

1. O(n^10)

• 경우의 수가 N^8개고, 각 경우를 검사하는데 N^2이므로 O(N^10) 알고리즘을 설계할 수 있음

• 혹시 설계한다면 두 직사각형이 겹치는지를 잘 체크해줘야 함 ^^;

• 코이스터디 서버가 초당 10^8번 연산한다는 가정하에.. 250^10 / 10^8 = 10^16초!!!

• O(n^10) 복잡도를 O(n^3)으로 줄이는 게 가능할까?

Page 5: IOI 2005 정원 분할 (2015.03.05)

2. O(n^8)

• 직사각형의 넓이를 O(1) 만에 구할 수 있다면 사각형의 넓이를 빠르게 계산할 수 있다.

• 2차원 배열을 잡고, S[i][j]를 (1,1) ~ (i,j) 사각형의 넓이라 정의하자

Page 6: IOI 2005 정원 분할 (2015.03.05)

2. O(n^8)• 만약에 내가 (a,b) ~ (c,d) 점을 양 끝으로 하는 사각형의

넓이를 구하고 싶다면?

• 먼저 S[c][d]를 구한 이후 적당히 다른 넓이를 빼 줘야 할 것이다.

• 일단 S[a-1][d]와 S[c][b-1]을 빼주자.

• 하지만 어떠한 영역은 두번 빼주는 일이 발생.

• 그래서, 두번 빠진 영역인 S[a-1][b-1]은 다시 더해주기!

Page 7: IOI 2005 정원 분할 (2015.03.05)

2. O(n^8)

• 이 과정에 의하면 (a,b) ~ (c,d) 사각형의 넓이는, S[c][d] - S[a-1][d] - S[c][b-1] + S[a-1][b-1]

• 포함배제 원리!

• S[i][j]를 계산하는데 n^2니까 총 시간 복잡도는 O(n^4)

• 하지만, S[i][j]를 계산할때도 포함배제를 쓸 수 있음!

Page 8: IOI 2005 정원 분할 (2015.03.05)

2. O(n^8)

• S[i][j] = S[i-1][j] + S[i][j-1] - S[i-1][j-1] + (i,j) 점의 장미의 개수

• (i,j) 점의 장미의 개수를 기준으로 이항하면 당연한 결과!

• 이 방법을 토대로, 순서대로 S[i][j]를 채워나갈 수 있음

• 한번 채우는데 O(1) 시간이 걸리므로 총 시간은 O(n^2)

• O(n^2)의 깔끔한 전처리로 직사각형의 넓이 계산 완료

Page 9: IOI 2005 정원 분할 (2015.03.05)

notes on O(n^8) solution• 부분합은 되게 중요하고 흥미로운 개념이다

• (사실 내가 좋아한다)

• 일단 당연히 1차원에서도 사용 가능한 개념이며

• 비슷한 응용으로 “변홧값 배열” 이라는 것도 있다

• 관심이 있으면 이것저것 알아보길!

• 나코더에서도 자주 할 듯 하다

Page 10: IOI 2005 정원 분할 (2015.03.05)

3. O(n^5)

• O(n^8)을 O(n^5)로 바꾸기 위해서는 상태의 수를 줄여나가야 함

• 지금까지 문제에서는 “두 직사각형의 경우의 수”를 모두 나열했지만,

• 굳이 그렇게 하지 않아도 모든 경우의 수를 나열할 수 있는 방법을 찾아야 함.

• 이 방법을 찾는게 문제의 가장 중요한 부분!

Page 11: IOI 2005 정원 분할 (2015.03.05)

3. O(n^5)

• 문제에서는 두개의 겹치지 않는 직사각형을 구하라고 하였음.

• 두 직사각형은 겹치지 않기 때문에, 두 직사각형 사이를 가로선이나 세로선으로 나눌 수 있음.

• 가로선과 세로선의 모든 경우의 수는 당연하게도 O(n).

• 가로선 위 아래 (세로선 왼쪽 오른쪽)로 고려해야 할 직사각형은 1개 뿐임.

Page 12: IOI 2005 정원 분할 (2015.03.05)

3. O(n^5)

• 직사각형을 나누는 가짓수 O(n)

• 나눠진 직사각형 안에서 모든 경우를 시도해 보는 건 아래 O(n^4) 위 O(n^4) -> O(n^4)

• 총 가짓수 = O(n^5)

• 상태는 이정도로 충분함. 이제는 계산 시간을 줄이자!

Page 13: IOI 2005 정원 분할 (2015.03.05)

4. O(n^4)

• 잘 생각해 보면 우리는 같은 직사각형을 여러번 구하고 있다

• 물론 같은 직사각형을 n^4번 구하던 아까보단 낫지만, 지금 구하는 n번도 사치이다.

• 어떻게 줄여야 할까?

• 직사각형을 마구잡이로 잡지 말고 우하단 점 (i,j) 를 고정시킨 채로 잡아 보자.

Page 14: IOI 2005 정원 분할 (2015.03.05)

4. O(n^4)• 직사각형을 마구잡이로 잡지 말고 우하단 점 (i,j) 를 고정시킨

채로 잡아 보자.

• 한쪽 점을 잡았으면 이후 고를 수 있는 점의 경우의 수는 O(n^2)

• 이 점들을 다 시도해 본 후 최적의 직사각형을 R1[i][j]에 저장한다면 이 경우의 시간 복잡도는 O(n^4)

• 이는 위쪽 / 왼쪽 사각형을 고를 때 유용하게 쓸 수 있음

• 반대쪽은 좌상단 점을 고정시킨 채로 똑같이!

Page 15: IOI 2005 정원 분할 (2015.03.05)

4. O(n^4)• 중앙선의 가짓수는 아까도 말했지만 O(n)개

• 처음에 앞서 말한 표를 계산해 놓으면 이후 O(n^2) 번 배열에 접근하면 최적값을 구할 수 있음.

• 실제 계산은 벌써 O(n^3)! 오예!

• (참고로, O(n^2)에 전처리 해서 O(n)만에 할 수도 있음. 관심이 있으면 연구해보길)

• 이제 직사각형을 빠르게 구해야 한다!

Page 16: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)• 대망의 O(n^3)!

• O(n^3)을 만들어내는 방법은 아까와 비슷하지만,

• 한쪽 점을 잡고 직사각형을 계산할때 O(n^2)개를 모두 둘러보는 게 아니라 O(n)개의 점만 방문한다는 데 의외가 있다.

• 일종의 상태 줄이기라고 볼 수 있다.

• Sliding Window라고 불리는 중요한 테크닉이니 잘 보길!

Page 17: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)

• (i,j) 점을 기준으로 한 직사각형에서 존재하는 장미의 수

• (예시임)

6 5 4 3 2

5 4 4 3 2

4 3 3 2 2

4 3 3 2 2

3 2 2 2 1

Page 18: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)

• (i,j) 점을 기준으로 한 직사각형에서 존재하는 장미의 수

• K = 3인 점을 색칠.

6 5 4 3 2

5 4 4 3 2

4 3 3 2 2

4 3 3 2 2

3 2 2 2 1

Page 19: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)

• (i,j) 점을 기준으로 한 직사각형에서 존재하는 장미의 수

• 우리는 둘레를 최소화하고 싶기 때문에 저 점은 필요없음!

6 5 4 3 2

5 4 4 3 2

4 3 3 2 2

4 3 3 2 2

3 2 2 2 1

Page 20: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)

• (i,j) 점을 기준으로 한 직사각형에서 존재하는 장미의 수

• 점의 개수는 최대 n개 <- 상태수 감소!

6 5 4 3 2

5 4 4 3 2

4 3 3 2 2

4 3 3 2 2

3 2 2 2 1

Page 21: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)

• (i,j) 점을 기준으로 한 직사각형에서 존재하는 장미의 수

• 이렇게 쭉 길을 따라갈 수 있다면??

6 5 4 3 2

5 4 4 3 2

4 3 3 2 2

4 3 3 2 2

3 2 2 2 1

Page 22: IOI 2005 정원 분할 (2015.03.05)

5. O(n^3)• 맨 처음에 좌표를 오른쪽 위로 설정.

• 한 줄씩 왼쪽으로 가면서….

• K보다 크거나 같은 가장 낮은 점까지 이동!

• 만약 K와 같은 점이라면 최솟값을 갱신!

• 위로 올라갈 필요가 없다는 것은 자명.

• O(n)에 사각형을 모두 열거할 수 있다!’

• 질문 : 왜 이중 루프인데 O(n^2)이 아닐까??

Page 23: IOI 2005 정원 분할 (2015.03.05)

O(n^10) -> O(n^3)• 1. 모든 방법을 열거하는게 O(n^10)

• 2. 사각형을 빠르게 계산하면 O(n^8)

• 3. 상태를 적절히 줄이면 O(n^5)

• 4. 중복호출 낭비를 줄이면 O(n^4)

• 5. Sliding Window Technique으로 O(n^3)까지!

• 다 중요함 ㅋㅋㅋㅋㅋ

Page 24: IOI 2005 정원 분할 (2015.03.05)

Conclusion

• O(n^10)의 끔찍한 복잡도를 O(n^3)으로 바꾸는 과정을 보여줌

• 정보 문제를 풀때 가능한 상태를 모두 생각해 본 후 어떻게 하면 계산 시간과 상태를 줄일 수 있는지에 대해 고민해 볼 수 있는 재미있는 문제임!

• 어려운 문제인데 수고했음 ㅠㅠ

Page 25: IOI 2005 정원 분할 (2015.03.05)

Link

• 복습 문제 : http://koistudy.net/?mid=prob_page&NO=709

• 심화 문제 : http://koistudy.net/?mid=prob_page&NO=338

• 풀이 링크 : amugelab.tistory.com/34