Bir problem üzerinde düşünürken, aşağıdaki görevi çözen verimli bir algoritma oluşturmam gerektiğini fark ettim:
Sorun: tarafları eksenlere paralel olan iki boyutlu bir yan taraf kare kutusu verilir . Üstünden bakabiliriz. Bununla birlikte, yatay segmentler de vardır. Her segment bir tamsayıdır sahip -coordinate ( ) ve -coordinates ( ) ve bağlanır noktası ve en (önceki Resim aşağıda).
Kutunun üstündeki her birim segment için, bu segmente bakarsak kutunun içinde ne kadar derin görünebileceğimizi bilmek isteriz.
Örnek: aşağıdaki resimdeki gibi bulunan ve segmenti verildiğinde sonuç . Kutunun içine ne kadar derin ışık girebileceğine bakın.
Neyse ki bizim için hem ve olan oldukça küçük ve biz off-line hesaplamalar yapabilirsiniz.
Bu sorunu çözmenin en kolay algoritması kaba kuvvettir: her segment için tüm diziyi çaprazlayın ve gerektiğinde güncelleyin. Ancak, bize çok etkileyici bir vermez .
Büyük bir gelişme, sorgu sırasında segment üzerindeki değerleri en üst düzeye çıkarabilen ve son değerleri okuyabilen bir segment ağacı kullanmaktır. Daha fazla açıklamayacağım, ancak zaman karmaşıklığının olduğunu görüyoruz .
Ancak, daha hızlı bir algoritma buldum:
anahat:
Segmentleri azalan koordinatına göre sıralayın (sayma sıralamasının bir varyasyonunu kullanarak doğrusal zaman). Şimdi, eğer herhangi bir birim segmenti daha önce herhangi bir segment tarafından kaplanmışsa, aşağıdaki hiçbir segmentin artık bu birim segmentinden geçen ışık demetini bağlayamayacağını unutmayın. Sonra kutunun üstünden altına doğru bir çizgi süpürme yapacağız.
Şimdi bazı tanımları tanıtalım : birim bölümü, x- koordinatları tamsayı olan ve uzunluğu 1 olan taramadaki hayali bir yatay bölümdür. Süpürme işlemi sırasında her bölüm işaretlenmemiş olabilir (yani, kutunun üst kısmı bu segmente ulaşabilir) veya işaretli (karşıt durum). Her zaman işaretlenmemiş x 1 = n , x 2 = n + 1 olan bir x birimi segmentini düşünün . Ayrıca S 0 = { 0 } , S 1 = . Her kümede,aşağıdakiişaretlenmemişbölümlebirlikteardışıkişaretli bir x birimi birimi (varsa) yeralacaktır.
Bu segmentler üzerinde çalışabilen ve verimli bir şekilde ayarlanabilen bir veri yapısına ihtiyacımız var. Maksimum x- birim segment indeksini ( işaretlenmemiş segmentin endeksi) tutan bir alan tarafından genişletilen bir birleştirme birliği yapısı kullanacağız .
Şimdi segmentleri verimli bir şekilde idare edebiliriz. En şimdi düşünüyoruz diyelim -inci başlar segmentin ( "sorgusu" diyoruz), x 1 ve uçları x 2 . İ- segmentinin içinde yer alan tüm işaretlenmemiş x- birimi segmentlerini bulmamız gerekir (bunlar tam olarak ışık demetinin yolunu bitireceği segmentlerdir). Aşağıdakileri yapacağız: ilk olarak, sorgunun içindeki ilk işaretlenmemiş segmenti buluruz ( x 1'in içerdiği kümenin temsilcisini bulun ve tanımı gereği işaretlenmemiş segment olan bu kümenin maksimum dizinini alın ). Sonra bu endeks , sorgunun içindedir, sonuca ekleyin (bu segment için sonuç y'dir ) ve bu dizini işaretleyin ( x ve x + 1 içerenbirleşimkümeleri). Ardından,işaretlenmemiştümsegmentleribulana kadar bu işlemi tekrarlayın, yani bir sonrakiSorgubulbize dizin x ≥ x 2 verir .
Her bir birleşim işleminin yalnızca iki durumda gerçekleştirileceğini unutmayın: ya bir segmenti düşünmeye başlarız ( kez olabilir) ya da sadece bir x- birim segmenti işaretledik (bu n kez olabilir). Bu nedenle, genel karmaşıklığı O ( ( n- + m ) α ( n ) ) ( α olan bir Ackermann fonksiyonu ters ). Bir şey net değilse, bu konuda daha fazla ayrıntı verebilirim. Belki biraz zamanım varsa resim ekleyebilirim.
Şimdi "duvara" ulaştım. Doğrusal bir algoritma bulamıyorum, ancak bir tane olması gerektiği anlaşılıyor. İki sorum var:
- Yatay segment görünürlük problemini çözen bir doğrusal zaman algoritması ( ) var mı?
- Değilse, görünürlük sorununun olduğunun kanıtı nedir?