ioi 2005 정원 분할 (2015.03.05)

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

Upload: jaehyun-koo

Post on 08-Aug-2015

60 views

Category:

Software


5 download

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