Program to find number of sets of k-non-overlapping line segments in Python

Suppose we have n points on a line, where the ith point (from 0 to n-1) is at position x = i, we have to find the number of ways we can draw exactly k different non-overlapping line segments such that each segment covers two or more points. The endpoints of each line segment must have integral coordinates. The k line segments do not have to cover all given n points, and they can share endpoints. If the answer is too large, then return result mod 10^9+7.

So, if the input is like n = 4, k = 2, then the output will be 5 because we can make five possibilities: [(0 to 2),(2 to 3)], [(0 to 1),(1 to 3)], [(0 to 1),(2 to 3)], [(1 to 2),(2 to 3)] and [(0 to 1),(1 to 2)].

Algorithm

To solve this, we will follow these steps ?

  • m := 10^9 + 7 (for modulo operation)
  • n := n - 1 (convert to number of intervals between points)
  • Define a recursive function dp(i, covered, j) where:
    • i = current position
    • covered = whether current position is already covered by a segment
    • j = number of segments formed so far
  • Base cases:
    • if i is same as n, then return true if j equals k, otherwise false
    • if j > k, then return 0 (invalid state)
  • For each position, we can:
    • Not start a new segment: dp(i + 1, False, j)
    • Start a new segment: dp(i + 1, True, j + 1)
    • If covered, continue current segment: dp(i + 1, True, j)
  • Return ans mod m

Example

Let us see the following implementation to get better understanding ?

def solve(n, k):
    m = 10 ** 9 + 7
    n -= 1
    
    # Memoization dictionary
    memo = {}
    
    def dp(i, covered, j):
        # Base case: reached the end
        if i == n:
            return j == k
        
        # Invalid case: too many segments
        if j > k:
            return 0
        
        # Check if already computed
        state = (i, covered, j)
        if state in memo:
            return memo[state]
        
        # Option 1: Don't start segment at position i
        ans = dp(i + 1, False, j)
        
        # Option 2: Start new segment at position i
        ans += dp(i + 1, True, j + 1)
        
        # Option 3: If already covered, continue current segment
        if covered:
            ans += dp(i + 1, True, j)
        
        ans = ans % m
        memo[state] = ans
        return ans
    
    return dp(0, False, 0)

# Test the function
n = 4
k = 2
result = solve(n, k)
print(f"Number of ways to draw {k} non-overlapping segments with {n} points: {result}")

The output of the above code is ?

Number of ways to draw 2 non-overlapping segments with 4 points: 5

How It Works

The algorithm uses dynamic programming with memoization to avoid recalculating the same subproblems. At each position, we have three choices:

  • Don't start a segment: Move to next position without starting a new segment
  • Start a new segment: Begin a new segment at current position
  • Continue segment: If already in a segment, extend it to the next position

Alternative Implementation

Here's a cleaner version without memoization for better understanding ?

def solve_simple(n, k):
    m = 10 ** 9 + 7
    n -= 1
    
    def dp(i, covered, j):
        if i == n:
            return j == k
        if j > k:
            return 0
            
        ans = dp(i + 1, False, j) + dp(i + 1, True, j + 1)
        if covered:
            ans += dp(i + 1, True, j)
        return ans % m
    
    return dp(0, False, 0)

# Test with different values
test_cases = [(4, 2), (5, 1), (3, 1)]

for n, k in test_cases:
    result = solve_simple(n, k)
    print(f"n={n}, k={k}: {result} ways")

The output of the above code is ?

n=4, k=2: 5 ways
n=5, k=1: 10 ways
n=3, k=1: 3 ways

Conclusion

This problem uses recursive dynamic programming to count non-overlapping line segments. The key insight is tracking whether we're currently in a segment and how many segments we've completed. The solution efficiently handles the exponential search space through memoization.

---
Updated on: 2026-03-26T13:50:55+05:30

409 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements