Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Python

Chương trình đếm số đường thẳng giao nhau trong khoảng cho trước trong Python

Cho danh sách các cặp (m, c) đại diện cho đường thẳng y = mx + c. Cho khoảng [l, h]. Đếm số đường thẳng có giao điểm với đường thẳng khác trong khoảng x ∈ [l, h].

Ví dụ

Input: lines=[[4,6],[-6,10],[8,12]], l=0, h=2 → Output: 2

Đường 4x+6 và -6x+10 giao nhau trong [0,2]. Đường 8x+12 không giao với hai đường kia trong khoảng này.

Thuật toán (Sweep Line tại hai đầu mút)

Đường thẳng y = mx + c tại x=l có giá trị y_l = ml + c, tại x=h có y_h = mh + c. Hai đường giao nhau trong [l,h] ⟺ thứ tự của chúng tại x=l khác thứ tự tại x=h.

  1. Tính mảng seg = [(y_l, y_h, index)] cho mỗi đường
  2. Sắp xếp seg theo y_l
  3. Duyệt seg theo thứ tự y_l tăng dần:
    • Nếu cùng y_l (song song tại l) → cả hai giao nhau
    • Theo dõi max y_h đã thấy. Nếu y_h hiện tại ≤ max_y_h → giao nhau
  4. Duyệt ngược seg (theo y_l giảm dần):
    • Theo dõi min y_h. Nếu y_h hiện tại ≥ min_y_h → giao nhau
  5. Đếm số đường bị đánh dấu giao nhau

Mã nguồn

from collections import Counter

def solve(input_list, l, h):
    seg = [(m * l + c, m * h + c, i) for i, (m, c) in enumerate(input_list)]
    seg.sort()
    ans = [0] * len(input_list)
    c = Counter(seg)
    
    # Kiểm tra trùng y_l
    for (x, y, i) in seg:
        if c[x] > 1:
            ans[i] = 1
    
    # Duyệt tăng dần y_l
    max_c = -(10 ** 10)
    prv = -(10 ** 10)
    for (x, y, i) in seg:
        if x == prv:
            ans[i] = 1
        if y <= max_c:
            ans[i] = 1
        max_c = max(max_c, y)
        prv = x
    
    # Duyệt giảm dần y_l
    min_c = 10 ** 10
    prv = 10 ** 10
    for (x, y, i) in seg[::-1]:
        if x == prv:
            ans[i] = 1
        if y >= min_c:
            ans[i] = 1
        min_c = min(min_c, y)
        prv = x
    
    return sum(ans)

print(solve([[4, 6], [-6, 10], [8, 12]], 0, 2))  # Output: 2

Giải thích trực quan

Đường thẳng là hàm tuyến tính. Hai đường giao nhau trong đoạn ⟺ chúng "cắt" nhau, tức là thứ tự y tại l ngược với thứ tự y tại h. Thuật toán phát hiện nghịch thế (inversion) trong dãy y_h khi sắp xếp theo y_l.