Düzlemi bölen daireler


23

Görev

Düzlemde y = 0 çizgisindeki merkezleriyle bir dizi daire verilecektir . Hiçbir çemberin birden fazla ortak noktaya sahip olmadığı garanti edilir.

Göreviniz, dairelerin kaç uçağı böldüğü konusunda bölgeleri belirlemek. Bir bölge, dairelerin hiçbiriyle kesişmeyen, en fazla bitişik bitişik nokta kümesidir.

Çevrelerin açıklaması verildiğinde bu cevabı hesaplayan bir program yazmalısınız.


İşte bir örnek:

örnek 1

Sol tarafta, düzlemde çizilen daireleri görüyorsunuz. Bununla birlikte, resmin sağ yarısında, daireler tarafından üretilen bölgeler belirgin bir şekilde renklendirilir (bölge başına bir renk). Bu örnekte altı bölge var.


Giriş

Girişin ilk satırında bir sayı, Nizlenmesi gereken daire açıklamalarının sayısı bulunur. Bu çizgi isteğe bağlıdır, eğer çözümünüz onsuz çalışıyorsa sorun değil.

Aşağıdaki Niki tamsayı içeren her satır, x i ve r i > 0 , merkezi bir çevre temsil (x i , 0) ve yarıçapı r i .

Hiçbir çemberin birden fazla ortak noktaya sahip olmadığı garanti edilir. Bundan başka, bu garanti x i ve r ı aşmamaktadır 10^9(da, bir 32-bit tamsayı sığacak şekilde) mutlak değer olarak.


Giriş olabilir:

  • STDIN'den oku

  • Igeçerli dizindeki bir dosyadan oku

Alternatif olarak, giriş olabilir:

  • Genel değişkende bir dize olarak kullanılabilir (yeni satırlar dahil)

  • yığında


Çıktı

Bu, üretilen bölgelerin sayısı olan tek bir tamsayı olmalıdır. Bu STDOUT ya Oda geçerli dizinde bir dosyaya yazılmalıdır .


kurallar

  • Bayt cinsinden en kısa kod kazanır

  • Kodunuzda çalışma zamanı + alan karmaşıklığı polinomu yoksa, +200 bayt ceza n

  • Beklenen en kötü durum için çalışma süresinde -100 bayt bonus + alan karmaşıklığı O(n log n)

  • Beklenen en kötü durum için çalışma süresinde -50 baytlık bonus + alan karmaşıklığı O(n)

  • Deterministik çalışma zamanı + uzay karmaşıklığı için -100 bayt bonus O(n)

Çalışma süresini değerlendirirken:

  • Karma tabloların O(1), işlemlerin sırası ve giriş verilerinden bağımsız olarak ekleme, silme ve arama için beklenen çalışma zamanının beklediğini varsayın . Bu, uygulamanın randomizasyon kullanıp kullanmadığına bağlı olarak doğru olabilir veya olmayabilir.

  • Programlama dilinizin yerleşik türünün , girdi sırasının büyüklüğü olan deterministik O(n log n)zaman aldığını varsayalım n.

  • Giriş numaralarındaki aritmetik işlemlerin sadece O(1)zaman alacağını varsayın .

  • GiriĢ numaralarının sabit olması gerektiğine inanmayın, ancak pratik nedenlerden ötürü. Bu, radix sıralama veya sayma sıralama gibi algoritmaların doğrusal zaman olmadığı anlamına gelir. Genel olarak, çok büyük sabit faktörlerden kaçınılmalıdır.


Örnekler

Giriş:

2 
1 3
5 1

Çıktı: 3


Giriş:

3
2 2
1 1
3 1

Çıktı: 5

4
7 5
-9 11
11 9
0 20

Giriş:

9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2

Çıktı: 11


İpuçları

Çok küçük bir çözüm için aşağıdaki fikri kullanabiliriz. Daireler kümesini X ekseni ile kesiştirip kesişme noktalarını düzlemsel bir grafikte düğümler olarak yorumlayalım:

görüntü tanımını buraya girin

Her daire bu grafikte tam olarak 2 kenar üretir ve en fazla iki düğüm oluşturur. Toplam ayrı sol veya sağ kenarlık sayısını takip etmek için bir karma tablo kullanarak düğüm sayısını sayabiliriz.

Ardından Euler karakteristiği formülünü , grafiğin bir çiziminin yüz sayısını hesaplamak için kullanabiliriz :

V - E + F - C = 1

F = E - V + C + 1

CBağlı bileşenlerin sayısını hesaplamak için ilk önce derinlemesine bir arama kullanabiliriz .


Not: Bu sorun bir fikirden ödünç alınmıştır. yakın tarihli bir Hırvat programlama yarışmasından , ancak lütfen çözüm ana hatlarına bakarak hile yapmayın. :)


Bu ikramiyelerin bazıları kandırıyor mu?
user2357112, 23.02'de Monica

@ user2357112 Bunu kanıtlayamazsanız, yapamayacağınızı varsaymayın;)
Niklas B.

Eh, girişleri bir makine tamsayısına sığması garanti edilirse, radix türünü kullanabilir ve O (n) diyebiliriz. Kısıtlı giriş büyüklüğü varsaymaktan nefret ediyorum, çünkü kesinlikle konuşursak, bu, son derece olası birçok giriş olduğu anlamına gelir.
user2357112,

@ user2357112 Hayır, asimptotik değerleri değerlendirirken sınırlandırılacak olan tamsayıları kabul edemeyeceğinizi söyledim, bu yüzden ne radix sıralaması ne de sayma sıralaması doğrusal zaman ve boşluk olmaz. Bir sözcüğe uymaları sadece aritmetik "gerçek" O (1) yapmak ve pratik nedenlerden dolayı (çoğu dilde sınırlı değişken genişlik)
Niklas B.

@NiklasB. süper doğrusal karmaşıklığa sahip tek bileşenin sıralama olduğu bir algoritmaya sahipsem, n log nbonus almak için eğer dilim hızlı sıralama kullanıyorsa birleştirme sıralamasını uygulamak zorunda mıyım ? Ayrıca yeni kavramsal olarak yeni bir çözümüm var. Eskisinin yerine yeni bir cevap yazmalı mıyım? (Eski çözümü tercih ederim, yeni çözümüm doğru olmasa diye)
Martin Ender

Yanıtlar:


2

Mathematica, 125 122 - 150 = -28 karakter

Yerleşik fonksiyonun karmaşıklığını bilmiyorum ConnectedComponents.

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&

Kullanımı:

1+{-1,2,1}.Length/@{VertexList@#,EdgeList@#,ConnectedComponents@#}&@Graph[(+##)<->(#-#2)&@@@Rest@ImportString[#,"Table"]]&[
"9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2"]

11


Sanırım ConnectedComponentsdoğrusal beklenen en kötü durum karmaşıklığına sahip olduğunu güvenle söyleyebiliriz , bu yüzden O (n) bileşenleri varsa, bu iyi olur. Mathematica'yı anlamıyorum, bu yüzden genel olarak O (n) olup -150 bonus için uygun olup olmadığını söyleyemem? Bence öyle. Sadece STDIN'deki giriş ile mi çalıştırıyorum?
Niklas B.

@NiklasB. onun giriş yöntemi sadece bir dize değişkeni anonim bir işleve geçiyor. bu yüzden kalifiye olması gerektiğini düşünüyorum. Çıktıya gelince, Mathematica'da bu sadece konsol çıktısında biten sayıyla sonuçlanacak, bu da muhtemelen iyi olmalı.
Martin Ender

Bunun doğruluğunu onayladım, sanırım -28 puanla yeni lider bu. Tebrikler!
Niklas B.

@NiklasB. neden sadece 150? Algoritmanın hangi bölümü süper lineer en kötü durum karmaşıklığına sahip?
Martin Ender

@ m.buettner 150, O (n) beklenen süre içindir. Düğümler gibi rasgele sayılar içeren grafikler için, burada olduğu gibi kesin olarak tanımlanmış, CCS sayısını doğrusal zaman içinde bulamazsınız; bu, bağlı bileşenlere öğenin belirginliğini azaltarak gösterilebilir . Sanırım, asıl
Niklas B.

4

Ruby - 312 306 285 273 269 259 karakter

Bu cevabım, oldukça az karakter kullanan ve içinde çalışan diğer yaklaşımımın yerini aldı .O(n log n)

Tamam hadi gidelim. Yeni başlayanlar için sadece çalışan bir uygulama istedim, bu yüzden henüz algoritmik olarak optimize edilmemiş. Çevreleri en büyüğünden en küçüğüne sıralıyorum ve bir ağaç yapıyorum (diğer dairelerde bulunan daireler daha büyük olanların çocuklarıdır). Her iki işlem de O(n^2)en kötü ve O(n log n)en iyi ihtimalle gerçekleşir. Sonra alanları saymak için ağacın içinde tekrarlanırım. Bir çemberin çocukları tüm çapını doldurursa, iki yeni alan vardır, yoksa sadece bir tane vardır. Bu yineleme sürer O(n). Bu yüzden genel bir karmaşıklığa sahibim O(n^2)ve ne ödül ne de ceza almaya hak kazanıyorum.

Bu kod, girdiyi bir değişkende depolanacak daire sayısı olmadan bekler s:

t=[]
s.lines.map{|x|x,r=x.split.map &:to_i;{d:2*r,l:x-r,c:[]}}.sort_by!{|c|-c[:d]}.map{|c|i=-1;n=t
while o=n[i+=1]
if 0>d=c[:l]-o[:l]
break
elsif o[:d]>d
n=o[:c]
i=-1
end
end
n[i,0]=c}
a=1
t.map &(b=->n{d=0
n[:c].each{|c|d+=c[:d]}.map &b
a+=d==n[:d]?2:1})
p a

Ungolfed versiyonu (değişkende girdi bekleniyor string):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_i
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius, children:[]}
}
list.sort_by! { |circle| -circle[:d] }
tree = []
list.map { |circle|
  i = -1
  node = tree
  while c=node[i+=1]
    if circle[:x]<c[:l]
      break
    elsif circle[:x]<c[:r]
      node = c[:children]
      i = -1
    end
  end
  node[i,0] = circle
}
areas = 1
tree.map &(count = -> node {
  d = 0
  i = -1
  while c=node[:children][i+=1]
    count.call c
    d += c[:d]
  end
  areas += d == node[:d] ? 2 : 1
})
p areas

@NiklasB. evet bu test durumu iyi olurdu. Ağacımdaki kenarları tanımlayan ilişki, basitçe bir dairenin diğerine dahil edilmesidir. Açık daire birbirini içermeyen iki dairede bulunamadığından ("bir kesişme" koşulu nedeniyle), bunun bir DAG olabileceğini görmüyorum.
Martin Ender

Bir düğümün torunları da çocukları mı?
user2357112, 0

@ user2357112 hayır, çünkü yalnızca doğrudan ebeveynlerini ayırabilirler
Martin Ender

@NiklasB. Sorunuzdaki örnekle çalıştırırsam, anlarım 11. Yorumunuzdakiler için 9.
Martin Ender

@NiklasB. Aslında olsun, bekle 10ve 8benim ungolfed sürümü ile ancak 11ve 9benim şimdiki golfed sürümü ile: D
Martin Ender

2

Ruby, 203 183 173 133 - 100 = 33 karakter

Yani burada farklı bir yaklaşım. Bu sefer çevreleri en soldaki noktalarına göre sıralıyorum. En sol noktalarına temas eden daireler en büyüğünden en küçüğüne doğru sıralanır. Bunu alır O(n log n)(peki, Ruby hızlı sıralama kullanır, yani aslında O(n^2)ama birleştirme / öbek sıralama uygulamak bu zorluğun kapsamı dışındadır). Sonra ziyaret ettiğim çevrelerin en sol ve en sağdaki konumlarını hatırlayarak bu listeyi yineliyorum. Bu, bir dizi dairenin etrafındaki daha büyük bir daireye tam olarak bağlanıp bağlanmadığını saptamamı sağlar. Bu durumda, iki alt alan var, aksi halde sadece bir tane. Bu yineleme, yalnızca 100 karakterlik ödül için nitelendirilen O(n)toplam karmaşıklığı verir O(n log n).

Bu kod parçası, girişin, komut satırı argümanlarında dosya sayısı olmadan , daire sayısı olmadan sağlanmasını bekler :

l,r={},{}
a=1
$<.map{|x|c,q=x.split.map &:to_r;[c-q,-2*q]}.sort.map{|x,y|a+=r[y=x-y]&&l[x]?2:1
l[y]=1 if l[x]&&!r[y]
l[x]=r[y]=1}
p a

Ungolfed versiyonu (bir değişkene girdi bekliyor string):

list = []
string.split("\n").map { |x|
  m = x.split
  x,radius = m.map &:to_r
  list<<{x:x, d:2*radius, l:x-radius, r:x+radius}
}
list.sort_by! { |circle| circle[:l] + 1/circle[:d] }
l,r={},{}
areas = 1
list.map { |circle|
  x,y=circle[:l],circle[:r]
  if l[x] && r[y]
    areas += 2
  else
    areas += 1
    l[y]=1 if l[x]
  end
  r[y]=1
  l[x]=1
}
p areas

Maalesef bu, tüm büyük test durumları için başarısız oluyor. Yine de hızlı;) Bu sefer küçük bir başarısızlık örneğim yok, ancak test verilerini bağlantılı olduğum yarışma web sitesinde bulabilirsiniz (yarışma # 6)
Niklas B.

Başarısız olan ilk test çantası, ilk "gerçek" test durumu olan kruznice / kruznice.in.2'dir. Rasgele iç içe daireler ile düzgün çalışıyor mu?
Niklas B.

@NiklasB. teşekkürler, test davalarına bir göz atacağım (düzeltmek için yarın
Martin Ender

@NiklasB. Sorunu düşündüm ve örnek başarısız az 5 çevreleri gerektirir: -1 1 1 1 0 2 4 2 0 6. Bunu nasıl yarın akşama kadar düzelteceğimi düşüneceğim (umarım).
Martin Ender

Karmaşıklık analiziniz, ilişkisel dizi erişiminin sabit zaman olduğunu varsayıyor gibi görünmektedir. Bu en kötü durumda doğru gibi görünmüyor.
Peter Taylor

1

Julia - 260 - 100 (bonus) = 160

Daireleri köşeler (kesişme noktaları), kenarlar ve yüzler (düzlemin alanları) ile rakamlar olarak yorumlamak birbirimizi Euler karakteristiğini kullanarak ilişkilendirebiliriz , bu nedenle sadece sayılara sahip olmak için "köşeler" ve "kenarlar" sayısını bilmemiz gerekir "yüzler" veya düzlemin bölgeleri aşağıda yazılı formülü ile:Euler karakteristiği

GÜNCELLEME: Bir süre düşünerek, yöntemimle ilgili sorunun yalnızca bağlanmayan çevreler olduğu zamanlar olduğunu anladım, bu yüzden bir fikirle geldim, neden yapay olarak onları birleştirmiyorsunuz? Böylece bütün Euler formülünü tatmin edecek.

Çevreler Örneği

F = 2 + EV (V = 6, E = 9)

[İç içe dairelerle çalışma, bu nedenle genel durumlar için sorunun cevabı değil]

Kod :

s=readlines(open("s"))
n=int(s[1])
c=zeros(n,2)
t=[]
for i=1:n
    a=int(split(s[i+1]))
    c[i,1]=a[1]-a[2]
    c[i,2]=a[1]+a[2]
    if i==1 t=[c[1]]end
    append!(t,[c[i,1]:.5:c[i,2]])
end
e=0
t=sort(t)
for i in 1:(length(t)-1) e+=t[i+1]-t[i]>=1?1:0end #adds one edge for every gap
2+2n+e-length(unique(c)) # 2+E-V = 2+(2n+e)-#vertices

Programınızın başarısız olacağını düşünüyorum 2 -10 1 10 1.
Niklas B.

"Hiçbir çemberin birden fazla ortak noktaya sahip olmadığı garanti edilir." bu yüzden geçerli olmayacağını düşünüyorum :)
ÇKP

@CCP Sıfır ortak noktaları var. n=2, daireler (C=(-10,0), r=1)ve(C=(10,0), r=1)
Niklas B.

1
Euler özelliğini uygulamak için grafiğin bağlı olması gerekmez mi?
user2357112, Monica

1
Ah, işte basit bir durum: 4 0 2 1 1 10 2 11 1Ama size daha fazla test vakası sunabileceğimi sanmıyorum, bu biraz haksızlık olur
Niklas B

1

Spidermonkey JS, 308, 287 , 273 - 100 = 173

Sanırım bunu Ruby veya Python ile yeniden yazdıysam karakterleri kaydedebilirim.

Kod:

for(a=[d=readline],e={},u=d(n=1);u--;)[r,q]=d().split(' '),l=r-q,r-=-q,e[l]=e[l]||[0,0],e[r]=e[r]||[0,0],e[r][1]++,e[l][0]++
for(k=Object.keys(e).sort(function(a,b)b-a);i=k.pop();a.length&&a.pop()&a.push(0)){for([l,r]=e[i];r--;)n+=a.pop()
for(n+=l;l--;)a.push(l>0)}print(n)

Algoritma:

n = 1 // this will be the total
e = {x:[numLeftBounds,numRightBounds]} // imagine this as the x axis with a count of zero-crossings
a = [] // this is the stack of circles around the "cursor".  
       // values will be 1 if that circle's never had alone time, else 0
k = sort keys of e on x
for each key in k: // this is the "cursor"
  n += key[numLeftBounds] // each circle that opens has at least one space.
  k[numRightBounds].times {n += a.pop()} // pop the closing circles. if any were never alone, add 1
  k[numLeftBounds].times {a.push(alwaysAlone)} // push the opening circles
  if !a.empty():
     set the innermost circle (top of stack) to false (not never alone)
  fi
loop

Büyük O gösteriminde çok iyi değilim, ama bence bu O (n) çünkü her daireyi 3 kez etkili bir şekilde dolaştırıyorum (yarat, sola, sağa) ve ayrıca haritanın anahtarlarını sıralıyorum (ve O için sıralıyorum) ( n günlüğü n) ama bu kaybolur). Bu deterministik mi?


Birisi rdöngü ve ldöngü bir ifadede nasıl birleştirileceği konusunda herhangi bir tavsiye varsa , takdir ediyorum.
Değil Charles

Şerefe :) Bana göre çalışma zamanınız gerçekten O (n log n) 'dir, çünkü -100 olur. Tüm test vakalarından geçip geçmediğini size bildiririm.
Niklas B.

Güzel, programın ilk denemede tüm sınav vakalarını geçiyor. Bence böyle bir şey (yığın halinde tutulan bir devletin süpürme çizgisi), sorun yazarlarının resmi çözümü idi. Programınız toplam 173 puan alıyor
Niklas B.

@NiklasB. Teşekkürler!
Charles,

Örtüşen halkalar ile çok daha sağlam bir çözüm deniyordum .... o zaman sadece bir noktada kesişebileceklerini gördüm.
Charles,

-1

JavaScript (ES6) - 255 254 Karakterler - 100 250 Bonus = 155 4

R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Giriş dizesinin değişkende olduğunu varsayar Sve bölge sayısını konsoluna verir.

R=/(\S+) (\S+)/ym;                  // Regular expression to find centre and width.
N=1;                                // Number of regions
w=l=0;                              // Maximum width and minimum left boundary.
X=[];                               // A 1-indexed array to contain the circles.
                                    // All the above are O(1)
for(;m=R.exec(S);){                 // For each circle
    X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};
                                    // Create an object with w (width), l (left boundary)
                                    // and r (right boundary) attributes.
    l=k<l?k:l;                      // Update the minimum left boundary.
    w=j<w?w:j                       // Update the maximum width.
}                                   // O(1) per iteration = O(N) total.
M=[];                               // An array.
X.map(x=>M[(x.l-l+1)*w-x.w]=x);     // Map the 1-indexed array of circles (X) to a
                                    // sparse array indexed so that the elements are
                                    // sorted by ascending left boundary then descending
                                    // width.
                                    // If there are N circles then only N elements are
                                    // created in the array and it can be treated as if it
                                    // is a hashmap (associative array) with a built in
                                    // ordering and as per the rules set in the question
                                    // is O(1) per insert so is O(N) total cost.
                                    // Since the array is sparse then it is still O(N)
                                    // total memory.
s=[];                               // An empty stack
i=0;                                // The number of circles on the stack.
M.map(x=>{                          // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

Zaman karmaşıklığı şimdi O (N) 'dir.

Test Durumu 1

S='2\n1 3\n5 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Çıktılar: 3

Test Durumu 2

S='3\n2 2\n1 1\n3 1';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Çıktılar: 5

Test Durumu 3

S='4\n7 5\n-9 11\n11 9\n0 20';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Çıktılar: 6

Test Durumu 4

S='9\n38 14\n-60 40\n73 19\n0 100\n98 2\n-15 5\n39 15\n-38 62\n94 2';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Çıktılar: 11

Test Durumu 5

S='87\n-730 4\n-836 2\n-889 1\n-913 15\n-883 5\n-908 8\n-507 77\n-922 2\n-786 2\n-782 2\n-762 22\n-776 2\n-781 3\n-913 3\n-830 2\n-756 4\n-970 30\n-755 5\n-494 506\n-854 4\n15 3\n-914 2\n-840 2\n-833 1\n-505 75\n-888 10\n-856 2\n-503 73\n-745 3\n-903 25\n-897 1\n-896 2\n-848 10\n-878 50\n-864 2\n0 1000\n-934 6\n-792 4\n-271 153\n-917 1\n-891 3\n-833 107\n-847 3\n-758 2\n-754 2\n-892 2\n-738 2\n-876 2\n-52 64\n-882 2\n-270 154\n-763 3\n-868 72\n-846 4\n-427 3\n-771 3\n-767 17\n-852 2\n-765 1\n-772 6\n-831 1\n-582 2\n-910 6\n-772 12\n-764 2\n-907 9\n-909 7\n-578 2\n-872 2\n-848 2\n-528 412\n-731 3\n-879 1\n-862 4\n-909 1\n16 4\n-779 1\n-654 68\n510 490\n-921 3\n-773 5\n-653 69\n-926 2\n-737 3\n-919 1\n-841 1\n-863 3';
R=/(\S+) (\S+)/ym;N=1;i=w=l=0;for(X=[];m=R.exec(S);){X[N++]={w:j=m[2]*1,l:k=m[1]-j,r:k+2*j};l=k<l?k:l;w=j<w?w:j}M=[];X.map(x=>M[(x.l-l+1)*w-x.w]=x);s=[];M.map(x=>{while(i&&s[i-1].r<x.r)N+=s[--i].w?0:1;i&&(s[i-1].w-=x.w);s[i++]=x});while(i)N+=s[--i].w?0:1

Çıktılar: 105

Önceki versiyon

C=S.split('\n');N=1+C.shift()*1;s=[];C.map(x=>x.split(' ')).map(x=>[w=x[1]*1,x[i=0]*1+w]).sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d).map(x=>{while(i&&s[i-1][1]<x[1])N+=s[--i][0]?0:1;i&&(s[i-1][0]-=x[0]);s[i++]=x});while(i)N+=s[--i][0]?0:1

Yorumlarla:

C=S.split('\n');                    // Split the input into an array on the newlines.
                                    // O(N)
N=1+C.shift()*1;                    // Remove the head of the array and store the value as
                                    // if there are N disjoint circles then there will be
                                    // N+1 regions.
                                    // At worst O(N) depending on how .shift() works.
s=[];                               // Initialise an empty stack.
                                    // O(1)
C .map(x=>x.split(' '))             // Split each line into an array of the two values.
                                    // O(1) per line = O(N) total.
  .map(x=>[w=x[1]*1,x[i=0]*1+w])    // Re-map the split values to an array storing the
                                    // radius and the right boundary.
                                    // O(1) per line = O(N) total.

  .sort((a,b)=>(c=a[1]-2*a[0])==(d=b[1]-2*b[0])?b[0]-a[0]:c-d)
                                    // Sort the circles on increasing left boundary and
                                    // then descending radius.
                                    // O(1) per comparison = O(N.log(N)) total.
  .map(x=>{                         // Loop through each circle
    while(i&&s[i-1][1]<x[1])        // Check to see if the current circle  is to the right
                                    // of the circles on the stack;
      N+=s[--i][0]?0:1;             // if so, decrement the length of the stack and if the
                                    // circle that pops off has radius equal to the total
                                    // radii of its children then increment the number of
                                    // regions by 1.

                                    // Since there can be at most N items on the stack then
                                    // there can be at most N items popped off the stack
                                    // over all the iterations; therefore this operation
                                    // has an O(N) total cost.
    i&&(s[i-1][0]-=x[0]);           // If there is a circle on the stack then this circle
                                    // is its child. Decrement the parent's radius by the
                                    // current child's radius.
                                    // O(1) per iteration
    s[i++]=x                        // Add the current circle to the stack.
  });
while(i)N+=s[--i][0]?0:1            // Finally, remove all the remaining circles from the
                                    // stack and if the circle that pops off has radius
                                    // equal to the total radii of its children then
                                    // increment the number of regions by 1.
                                    // Since there will always be at least one circle on the
                                    // stack then this has the added bonus of being the final
                                    // command so the value of N is printed to the console.
                                    // As per the previous comment on the complexity, there
                                    // can be at most N items on the stack so between this
                                    // and the iterations over the circles then there can only
                                    // be N items popped off the stack so the complexity of
                                    // all these tests on the circles on the stack is O(N).

Toplam zaman karmaşıklığı, O (N.log (N)) olan sıralama dışındaki her şey için O (N) 'dir - ancak bunu bir kova türüyle değiştirmek, toplam karmaşıklığı O (N)' ye indirecektir.

Gerekli hafıza O (N).

Yapılacaklar listemde sırada ne var ... Tahmin et 150 karakterden daha kısa. Bitti


Kova sıralama yalnızca ortalama bir karmaşıklığa O(n)(aslında O(n+k)) sahiptir, ancak O(n^2)veya O(n log n)kovalar içinde kullanılan sıralama algoritmasına bağlı olarak en kötü durumdur, bu yüzden 50 karakterde yapmanız gerekir.
Martin Ender

@ m.buettner - Kova sıralama O (N) en kötü durum karmaşıklığında yapılabilir. Kovaların dikkatli seçimine ve kovalara atanacak O (1) algoritmasına dayanır. Daha önce yaptım (ve kanıtladım) ve sadece kodu JavaScript'e aktarmam gerekiyor. Yukarıdaki algoritma zaten O (N.log (N)) 'dir, bu nedenle tek iyileştirme O (N) sıralama algoritması elde etmektir.
MT0

Bu kanıt ve buna uygun kova seçimi ile ilgilenirim. :)
Martin Ender

cs.princeton.edu/~dpd/Papers/SCG-09-invited/… (sayfa 556) bir O (N) kova türüne bir örnek verir. archive.org/stream/PlanarityTestingByPathAddition/… (sayfa 75) bir O (N) birleşik DFS arama ve kova türüne bir örnek verir (zaman karmaşıklığı sayfa 76'da ele alınmıştır).
MT0

1
@ Mt0 tutun, sorunun karmaşıklık bölümüne eklememi okuyabilirsin. Sınırsız sayılarla doğrusal zamanda sıralama kesinlikle imkansızdır
Niklas B.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.