• Home
  • About
    • Zzu-h photo

      Zzu-h

      주니어 Android 개발자입니다.

    • Learn More
    • Email
    • Instagram
    • Tistory
    • Github
  • Posts
    • All Posts
    • All Tags
    • All Categories
  • Projects

[BOJ] 1010 다리 놓기

11 May 2022

Reading time ~2 minutes

다리 놓기

링크: https://www.acmicpc.net/problem/1010

이전에 단순 코드로 해결한 적이 있었다. 링크
하지만, 시간제한이 들어가며 O(n^2)의 코드는 재채점 되어 실패가 되었다.

그래서 이를 다시 해결하기로 했고, 다음의 정답을 유추했다.
서쪽에 있는 점들이 선택한 동쪽 점들은 그 선이 교차가 되면 안되기에 서쪽의 있는 점들은 동쪽에 있는 점들에 의해 의존됨을 알 수 있다.
이 말은 동쪽에 있는 점들을 서쪽의 점 개수만큼 정하게 되면 서쪽은 자연스레 그 점들에 의해 배치된다는 것을 의미한다.
그렇다면, 동쪽의 점들 m개 중에서 서쪽의 점들 n개를 선택하면 된다.
이는 조합 공식으로 해결할 수 있다.


따라서, 조합의 코드를 해결하는데, n!/r!이므로 이를 아래와 같이 구현했다.

  • 정답 코드 ```kotlin import java.math.BigDecimal

class Main { companion object{ fun combination(n: Int, r: Int): BigDecimal{ var bigN = (1).toBigDecimal() var bigR = (1).toBigDecimal()

        (0 until r).forEach{
            bigN *= (n.toBigDecimal() - it.toBigDecimal())
            bigR *= (r.toBigDecimal() - it.toBigDecimal())
        }

        return bigN / bigR
    }

    @JvmStatic
    fun main(args: Array<String>){
        val c = readln().toInt()
        for(i in 0 until c){
            val item = readln().split(' ')

            println(combination(item[1].toInt(), item[0].toInt()))
        }
    }
} } ``` <br>


너무 빨리 풀어 조합 구하는 공식을 다른 방식으로 구현해보고자 한다.
조합은 다음의 공식이 성립한다.

nCr = (n-1)C(r-1) + (n-1)Cr

증명은 위키백과에서 가져왔다.

  • 증명: n명중 B라는 사람을 우선 빼놓고 생각하자. 그렇다면
    • n명중 A그룹에 들어갈 k명을 고르는 가짓수 = B를 무조건 A그룹에 포함하는 경우 + B를 무조건 배제하는 경우 = n-1명 중 k-1명 선정 + n-1명 중 k명 선정을 하는 가짓수이다.

위의 공식을 재귀함수를 이용해서 구현하면 손쉽게 구현할 수 있다.
다만, 기존에 구했던 데이터들은 다시 재사용 될 수 있다.
그렇기에 dp라는 배열에 이전에 계산했던 데이터라면, 그 값을 리턴해주고 종료한다.
또한, 해당 함수의 종료 조건은 n과 r이 같거나, r이 0에 도달했을 경우 그 값은 1로 마무리 된다.
구현한 코드를 확인하자.

  • 정답 코드
import java.math.BigDecimal

class Main {
    companion object{
        private const val dpSize = 31
        val dp = Array(dpSize) {Array(dpSize){(0).toBigDecimal()}}

        fun combinationWithDP(n: Int, r: Int): BigDecimal{
            if(dp[n][r] != (0).toBigDecimal()) return dp[n][r]
            if(n == r || r == 0) return (1).toBigDecimal()

            dp[n][r] = combinationWithDP(n - 1, r - 1) + combinationWithDP(n - 1, r)
            return dp[n][r]
        }

        @JvmStatic
        fun main(args: Array<String>){
            val c = readln().toInt()
            for(i in 0 until c){
                val item = readln().split(' ')

                println(combinationWithMemoization(item[1].toInt(), item[0].toInt()))
            }
        }
    }
}


PSBOJsilverdp Share Tweet +1