LeetCode每日一题(1621. Number of Sets of K Non-Overlapping Line Segments)

发布于:2023-01-10 ⋅ 阅读:(282) ⋅ 点赞:(0)

Given n points on a 1-D plane, where the ith point (from 0 to n-1) is at x = i, find the number of ways we can draw exactly k non-overlapping line segments such that each segment covers two or more points. The endpoints of each segment must have integral coordinates. The k line segments do not have to cover all n points, and they are allowed to share endpoints.

Return the number of ways we can draw k non-overlapping line segments. Since this number can be huge, return it modulo 109 + 7.

Example 1:

Input: n = 4, k = 2
Output: 5

Explanation: The two line segments are shown in red and blue.
The image above shows the 5 different ways {(0,2),(2,3)}, {(0,1),(1,3)}, {(0,1),(2,3)}, {(1,2),(2,3)}, {(0,1),(1,2)}.

Example 2:

Input: n = 3, k = 1
Output: 3

Explanation: The 3 ways are {(0,1)}, {(0,2)}, {(1,2)}.

Example 3:

Input: n = 30, k = 7
Output: 796297179

Explanation: The total number of possible ways to draw 7 line segments is 3796297200. Taking this number modulo 109 + 7 gives us 796297179.

Constraints:

  • 2 <= n <= 1000
  • 1 <= k <= n-1

首先这题我们要按线段来看, n 个点分割出 n-1 个线段, 每个线段要么是线, 要么是空。
假设 dp[n][k][0]是第 n 条线段为空时且此时一共有 k 条线的情况的组合数量, dp[n][k][1]是第 n 条线段为线且此时一共有 k 条线的情况的组合数量, 我们不难推出, dp[n][k][0] = dp[n-1][k][0] + dp[n-1][k][1], 也就是前一个线段时不管是空还是线,已存在 k 条线的组合数量, 之所以需要 n-1 时就完成 k 条线是因为此时考虑的是第 n 段为空的情况。第 n 段为线的情况是 dp[n][k][1] = dp[n-1][k-1][0] + dp[n-1][k-1][1] + dp[n-1][k][1], 这里面 dp[n-1][k-1][0]是第 n-1 段为空且有 k-1 条线的情况, dp[n-1][k-1][1]是第 n-1 段为线且有 k-1 条线的情况, 这两个比较好理解,就是到第 n-1 段为止已经完成了 k-1 条线,第 n 段作为一条长度为 1 的独立的线加入。dp[n-1][k][1]所考虑的情况是第 n-1 段已经有了 k 条线而且第 n-1 段为线的情况,此时第 n 段为线,但不是独立的线,是跟 n-1 这一段融合的线,看做是 n-1 段的延长

这题中等难度,但是做出来还是挺有成就感的



static M: i64 = 1000000007;

impl Solution {
    pub fn number_of_sets(n: i32, k: i32) -> i32 {
        let mut dp = vec![vec![vec![0, 0]; k as usize + 1]; n as usize - 1];
        dp[0][0][0] = 1;
        dp[0][1][1] = 1;
        for i in 1..n as usize - 1 {
            dp[i][0][0] = 1;
            for j in 1..k as usize + 1 {
                dp[i][j][0] = (dp[i - 1][j][0] + dp[i - 1][j][1]) % M;
                dp[i][j][1] = (dp[i - 1][j - 1][0] + dp[i - 1][j - 1][1] + dp[i - 1][j][1]) % M;
            }
        }
        ((dp[n as usize - 2][k as usize][0] + dp[n as usize - 2][k as usize][1]) % M) as i32
    }
}