나는 당신을 상당히 전형적인 스캔 라인 방식으로 공격 할 수 있다고 생각합니다.
그림의 맨 위에서 아래로 스윕하는 수평 스캔 라인을 먼저 고려하십시오. 스캔 라인이 가로 지르는 폭은 수직 세그먼트의 끝점을 지나갈 때만 변할 수 있습니다.
수평 주사선의 경우 수평선을 무시할 수 있습니다. 수직 세그먼트의 모든 끝점을 가져 와서 수직 위치별로 정렬합니다. (각 종점은 해당 종단의 "최상위"종점 또는 "종점"종점인지 여부를 알고 있음).
스캔 라인을 시뮬레이트하기 위해 정렬 된 목록을 처리합니다. empty로 초기화 된 "활성 세트"S를 유지 보수합니다. "최하위"종단점을 명중 할 때, S에 그 세그먼트를 추가하십시오. "종점"종점에 도달하면, S에서 그 세그먼트를 제거하십시오. 활성 세트의 폭이 항상 귀하의 제약 조건을 충족하는지 확인하십시오.
비교 기능의 수평 위치를 사용하여 활성 세트를 나타내는 균형 이진 트리 (예 : C++ std::set
)를 사용하십시오. 이렇게하면 집합에서 가장 왼쪽과 오른쪽 세그먼트의 O (1) 검색이 가능하므로 너비 계산은 O (1)입니다. 또한 O (log n) 삽입 및 제거가 가능하며 각 수직 세그먼트를 정확히 한 번 삽입하고 제거하므로 전체 스윕에는 O (n log n)이 필요합니다.
수직 주사선을 대칭으로 반복합니다.
각 정렬은 O (n log n)이고 각 스캔은 O (n log n)이며 각 방향에 대해 두 배입니다 ... 따라서 전체 알고리즘은 O (n log n)입니다.
볼록한 모양이나 오목한 모양? –
구멍이 있다면 너비가 구멍을 포함합니까? O 모양이 있다고 해봅시다. 중간에 너비가 2 또는 3이 될까요? (구멍을 가정하고 모든면이 개별 길이 1이었습니다) – corsiKa