일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- STL
- 프로그래밍언어론
- 라인
- 프로그래머스
- DP
- 스프링 프레임워크
- C/C++
- binary search
- 백준
- BFS
- C++
- 백트래킹
- 릿코드
- 라인플러스
- Python
- 시애틀
- 알고리즘
- spring
- dfs
- 머신러닝
- 모두를 위한 딥러닝
- leetcode
- Spring Framework
- 벤쿠버
- 딥러닝
- Java
- 다이나믹프로그래밍
- 파이썬
- jvm
- 스타벅스
- Today
- Total
케이스윔의 개발 블로그
[백준][DP] 1010번 다리놓기 본문
문제
서쪽의 N개의 사이트, 동쪽의 M개의 사이트가 주어질 때 다리를 놓을 수 있는 경우의 수를 구하시오.
문제 출처: 백준 온라인저지(https://www.acmicpc.net/problem/1010)
풀이
꽤 간단한 문제인데 (혼자) 함정아닌 함정에 빠져서 1시간정도 걸린 문제입니다. 동쪽에 M개의 사이트로 N개의 다리를 놓는 경우의 수이고 모든 다리는 똑같이 생겼을 것이기 때문에 조합의 수와 같다고 할 수 있습니다. 처음에 생각을 하지 않고 풀었는지 이 문제가 dp일까? 하면서 조합을 구하는 공식 n!/k!(n-k)! 을 바로 적용해버렸습니다. 테스트케이스는 올바르게 나왔지만 신중히 제출하기 위해 질문검색을 찾아보니 바로 오버플로우가 나는 것을 알 수 있었습니다. N, M이 30이하이지만 30!만 해도 int 범위를 벗어난다는 것을 고려하지 못했습니다. 해결하기위해서는 dp로 풀어야했습니다. 점화식 접근 자체는 쉬웠는데 n, m을 바꿔서 i, j로 생각하다보니 잘못 수식을 작성해서 잘 풀리지 않았었습니다. N개의 다리를 M개에 놓는 경우를 최종적으로 구하기 위해서 M개중에 N개를 고르는 조합을 구하는 공식을 응용해서 점화식을 세웠습니다. 차례대로 식을 변형시켜보겠습니다. dp[m][n] = m!/(n!(*m-n)!) -> dp[m][n-1] = m!/((n-1)!*(m-(n-1))!) = m!*n/(n!*(m-n+1)*(m-n)!) = dp[m][n]*n/(m-n+1) -> dp[m][n] = dp[m][n-1]*(m-n+1)/n 라는 결과가 나오게 됩니다. 보통 i번째의 값을 이용해서 i+1을 구하도록 점화식을 생각하는데 여기서는 n에서 n-1으로의 점화식을 만들어버려서 계산하는데 시간이 오래 걸려버렸습니다.. 그리고 2차원 배열이기때문에 이중 for문을 통해서 값을 업데이트시킬 때 m과 n을 어떠한 순서로 증가시켜야될 지 고민이 됐습니다. 그와함께 n이 1일 때의 문제가 떠올랐는데 모든 m에 대해서 dp[i][1]은 i라는 것을 통해 순서에 대한 고민을 없앨 수 있었습니다. 처음 dp[i][1]을 초기화 해준 다음 m과 n을 2에서 시작하는 이중for문으로 만들어주었습니다.
코드
'Algorithm > Dynamic Programming' 카테고리의 다른 글
[백준][DP] 1912번 연속합 (0) | 2018.12.14 |
---|---|
[백준][DP] 2225번 합분해 (0) | 2018.12.12 |
[백준][DP] 11053번 가장 긴 증가하는 부분 수열 (0) | 2018.12.04 |
[백준][DP] 1890번 점프 (0) | 2018.11.18 |
[백준 알고리즘] 11060번 점프 점프 (0) | 2018.01.11 |