ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[LeetCode]1621. Number of Sets of K Non-Overlapping Line Segments 动态规划js版

2022-02-27 06:31:35  阅读:237  来源: 互联网

标签:1621 终点 ways 线段 number js segments Segments dp


题目描述

LeetCode原题链接:1621. Number of Sets of K Non-Overlapping Line Segments

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 10^9 + 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 10^9 + 7 gives us 796297179.

 

Constraints:

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

题目分析

这道题可以用动态规划来做,就是状态量会比较多一些,可能不大好理解。题目中给了n和k,那肯定我们先需要一个二维 dp[i][j] ,其中每个位置表示前0~i这些点分成j段有几种分法。这个比较直观,最终的结果就是dp[n-1][k]。现在我们来看对于遍历到的任意一个位置i,(i, 0)这个点和已经出现的线段能组成哪些新的情况,就用example1中的示意图作为例子, 假设当前遍历到了i=2这个位置:

case1: 将上一个位置(即:(1,0)点)的最后一根线段延长到当前位置,此时 (2,0) 成为了上一个位置最后一根线段延长后的新的终点,没有新的线段产生;

case2/case3: 将上一个位置(即:(1,0)点)最后一根线段的终点最为起点,将当前位置 (2,0) 作为终点,产生了一条新的线段(蓝色线段);

注意这里为啥要把case2和case3分开呢?虽然它们都是以 (1,0) 为起点,(2,0) 为终点产生一条新线段,但由于 (1,0) 点之前的情况不同(空隙or某一线段终点),实际上最终结果是两种不同的情况。由此可见,我们还需要另外一种状态来标记某一点是否是最后一个线段的终点,即是否这个点之前挨着的是空隙。因此再在原有的二维dp数组上增加一个纬度,用来标识这种状态:

  • dp[i][j][0]: 前i个点分成j段并且i点不是最后一根线段终点时(最后一根线段没有延伸到i点)有几种分法
  • dp[i][j][1]: 前i个点分成j段并且i点是最后一根线段终点时(最后一根线段延伸到了i点)有几种分法

于是结合之前的分析,我们可以得到状态转移方程为:

  • dp[i][j][0] = dp[i-1][j][0] + dp[i-1][j][1]  (如果不能延伸到 (i,0) 点,那么就要求在上一位置 (i-1,0) 点就要分割成j段)
  • dp[i][j][1] = dp[i-1][j][0] + dp[i-1][j-1][1] + dp[i-1][j-1][0]  (如果能延伸到 (i,0)点,那么分别对应上图中的三种情况)

最后,初始化的时候 dp[0][0][0]=1,其余为0。最终结果返回 dp[n-1][k][0] + dp[n-1][k][1]

代码示例(JS)

 1 var numberOfSets = function(n, k) {
 2     let mod = 1000000007;
 3     let dp = new Array(n);
 4     for(let i = 0; i < n; i++) {
 5         dp[i] = new Array(k + 1);
 6         for(let j = 0; j <= k; j++) {
 7             dp[i][j] = new Array(2);
 8             dp[i][j].fill(0);
 9         }
10     }
11     dp[0][0][0] = 1;
12     for(let i = 1; i < n; i++) {
13         for(let j = 0; j <= k; j++) {
14             dp[i][j][0] = (dp[i-1][j][0] + dp[i-1][j][1]) % mod;
15             dp[i][j][1] = dp[i-1][j][1];
16             if(j > 0) {
17                 dp[i][j][1] = (dp[i][j][1] + dp[i-1][j-1][0] + dp[i-1][j-1][1]) % mod;
18             }
19         }
20     }
21     return (dp[n-1][k][0] + dp[n-1][k][1]) % mod;
22 };

标签:1621,终点,ways,线段,number,js,segments,Segments,dp
来源: https://www.cnblogs.com/barryyeee/p/15941420.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有