Vòng tròn phân chia mặt phẳng


23

Bài tập

Bạn sẽ được cung cấp một tập hợp các vòng tròn trong mặt phẳng với tâm của chúng trên đường thẳng y = 0 . Nó được đảm bảo rằng không có cặp vòng tròn nào có nhiều hơn một điểm chung.

Nhiệm vụ của bạn là xác định có bao nhiêu vùng trong đó các vòng tròn chia mặt phẳng. Một vùng là một tập hợp các điểm tiếp giáp tối đa bao gồm không giao nhau với bất kỳ vòng tròn nào.

Bạn nên viết một chương trình tính toán câu trả lời này khi được mô tả về các vòng tròn.


Đây là một ví dụ:

ví dụ 1

Ở phía bên trái, bạn nhìn thấy các vòng tròn được vẽ trong mặt phẳng. Tuy nhiên, ở nửa bên phải của hình ảnh, các vùng được tạo bởi các vòng tròn được tô màu rõ rệt (một màu cho mỗi vùng). Có sáu vùng trong ví dụ này.


Đầu vào

Dòng đầu tiên của đầu vào chứa một số, Nsố lượng mô tả vòng tròn cần theo dõi. Dòng này là tùy chọn, nếu giải pháp của bạn hoạt động mà không có nó, nó ổn.

NMỗi dòng sau đây chứa hai số nguyên, x ir i > 0 , đại diện cho một vòng tròn có tâm (x i , 0) và bán kính r i .

Nó được đảm bảo rằng không có cặp vòng tròn nào có nhiều hơn một điểm chung. Một điều chắc chắn nữa là x ir i không vượt quá 10^9giá trị tuyệt đối (vì vậy chúng thoải mái khớp với số nguyên 32 bit).


Đầu vào có thể là:

  • đọc từ STDIN

  • đọc từ một tập tin có tên Itrong thư mục hiện tại

Ngoài ra, đầu vào có thể là:

  • có sẵn dưới dạng một chuỗi (bao gồm cả dòng mới) trong một biến toàn cục

  • trên ngăn xếp


Đầu ra

Đây phải là một số nguyên duy nhất, số cho các vùng được sản xuất. Điều này nên được ghi vào STDOUT hoặc một tệp có tên Otrong thư mục hiện tại.


Quy tắc

  • Mã ngắn nhất tính bằng byte

  • Hình phạt +200 byte nếu mã của bạn không có đa thức thời gian chạy + không gian phức tạp trong n

  • Phần thưởng -100 byte cho thời gian chạy dự kiến ​​trong trường hợp xấu nhất + độ phức tạp của không gian O(n log n)

  • Phần thưởng -50 byte cho thời gian chạy dự kiến ​​trong trường hợp xấu nhất + độ phức tạp của không gian O(n)

  • Phần thưởng -100 byte cho thời gian chạy xác định + độ phức tạp không gian O(n)

Trong khi đánh giá thời gian chạy:

  • Giả sử rằng các bảng băm có O(1)thời gian chạy dự kiến ​​để chèn, xóa và tra cứu, bất kể chuỗi hoạt động và dữ liệu đầu vào. Điều này có thể đúng hoặc không, tùy thuộc vào việc triển khai có sử dụng ngẫu nhiên hay không.

  • Giả sử rằng loại dựng sẵn của ngôn ngữ lập trình của bạn cần O(n log n)thời gian xác định , trong đó nkích thước của chuỗi đầu vào.

  • Giả sử rằng các phép toán số học trên các số đầu vào chỉ mất O(1)thời gian.

  • Đừng cho rằng số đầu vào bị ràng buộc bởi một hằng số, mặc dù, vì lý do thực tế, chúng là. Điều này có nghĩa là các thuật toán như sắp xếp cơ số hoặc sắp xếp đếm không phải là thời gian tuyến tính. Nói chung, nên tránh các yếu tố hằng số rất lớn.


Ví dụ

Đầu vào:

2 
1 3
5 1

Đầu ra: 3


Đầu vào:

3
2 2
1 1
3 1

Đầu ra: 5

4
7 5
-9 11
11 9
0 20

Đầu vào:

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

Đầu ra: 11


Gợi ý

Chúng ta có thể sử dụng ý tưởng sau đây cho một giải pháp rất nhỏ gọn. Cho phép cắt các tập hợp các vòng tròn với trục X và diễn giải các điểm giao nhau dưới dạng các nút trong biểu đồ phẳng:

nhập mô tả hình ảnh ở đây

Mỗi vòng tròn tạo ra chính xác 2 cạnh trong biểu đồ này và tối đa hai nút. Chúng ta có thể đếm số lượng nút bằng cách sử dụng bảng băm để theo dõi tổng số đường viền trái hoặc phải riêng biệt.

Sau đó, chúng ta có thể sử dụng công thức đặc trưng Euler để tính số mặt của bản vẽ đồ thị:

V - E + F - C = 1

F = E - V + C + 1

Để tính toán C, số lượng các thành phần được kết nối, chúng ta có thể sử dụng tìm kiếm theo chiều sâu .


Lưu ý: Ý tưởng vấn đề này được mượn từ một cuộc thi lập trình gần đây của Croatia , nhưng xin đừng gian lận bằng cách xem các phác thảo giải pháp. :)


Là một số trong những phần thưởng giải mã?
user2357112 hỗ trợ Monica

@ user2357112 Đừng cho rằng điều đó không thể thực hiện được trừ khi bạn có thể chứng minh điều đó;)
Niklas B.

Chà, với các đầu vào được đảm bảo khớp với số nguyên của máy, chúng ta có thể sử dụng một loại cơ số và gọi nó là O (n). Tôi ghét giả định kích thước đầu vào bị hạn chế, bởi vì nói đúng ra, điều đó có nghĩa là có rất nhiều đầu vào có thể.
user2357112 hỗ trợ Monica

@ user2357112 Không, tôi đã nói rằng bạn không thể giả sử các số nguyên bị giới hạn trong khi đánh giá các tiệm cận, do đó, không sắp xếp radix hay sắp xếp đếm sẽ là thời gian và không gian tuyến tính. Rằng họ phù hợp với một từ chỉ là để làm cho arithologists "thực" O (1) và vì lý do thực tế (giới hạn biến đổi trong hầu hết các ngôn ngữ)
Niklas B.

@NiklasB. Nếu tôi có một thuật toán trong đó thành phần duy nhất có độ phức tạp siêu tuyến là sắp xếp, tôi phải thực hiện sắp xếp hợp nhất nếu ngôn ngữ của tôi sử dụng sắp xếp nhanh, để nhận được n log ntiền thưởng? Ngoài ra, tôi có giải pháp mới về khái niệm mới. Tôi có nên đăng một câu trả lời mới thay thế cái cũ? (Tôi thích cái trước hơn, trong trường hợp giải pháp mới của tôi không thực sự chính xác)
Martin Ender

Câu trả lời:


2

Toán học, 125 122 - 150 = -28 ký tự

Tôi không biết sự phức tạp của chức năng tích hợp ConnectedComponents.

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

Sử dụng:

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


Tôi nghĩ rằng chúng ta có thể giả định một cách an toàn rằng ConnectedComponentscó độ phức tạp trong trường hợp xấu nhất dự kiến ​​tuyến tính, vì vậy nếu có các thành phần O (n), điều này sẽ ổn. Tôi không hiểu Mathicala, vì vậy tôi không thể biết liệu đó có phải là O (n) hay không và có đủ điều kiện nhận phần thưởng -150 không? Tôi nghĩ rằng nó làm. Tôi chỉ chạy nó với đầu vào trong STDIN?
Niklas B.

@NiklasB. phương thức nhập của anh ta chỉ là truyền một biến chuỗi cho một hàm ẩn danh. Vì vậy, tôi nghĩ rằng nên đủ điều kiện. đối với đầu ra, trong Mathicala, điều này chỉ đơn giản sẽ dẫn đến số kết thúc ở đầu ra giao diện điều khiển, do đó có lẽ cũng sẽ ổn.
Martin Ender

Tôi đã xác minh tính đúng đắn của việc này, vì vậy tôi nghĩ với số điểm -28 đây là nhà lãnh đạo mới. Xin chúc mừng!
Niklas B.

@NiklasB. Tại sao chỉ có 150? Phần nào của thuật toán có độ phức tạp trường hợp xấu nhất?
Martin Ender

@ m.buettner 150 dành cho thời gian dự kiến ​​O (n). Đối với các biểu đồ có số tùy ý là các nút, được định nghĩa ngầm như ở đây, bạn không thể tìm thấy số lượng CC trong thời gian tuyến tính, có thể được hiển thị bằng cách giảm độ khác biệt của phần tử với các thành phần được kết nối. Tôi nghĩ rằng chúng ta cũng có thể giảm sự khác biệt của yếu tố đối với vấn đề ban đầu
Niklas B.

4

Ruby - 312 306 285 273 269 259 ký tự

Câu trả lời này đã được thay thế bởi cách tiếp cận khác của tôi , sử dụng ít ký tự hơn chạy vào O(n log n).

Được rồi đi thôi. Đối với người mới bắt đầu, tôi chỉ muốn một triển khai làm việc, vì vậy điều này chưa được tối ưu hóa về mặt thuật toán. Tôi sắp xếp các vòng tròn từ lớn nhất đến nhỏ nhất và xây dựng một cái cây (các vòng tròn được bao gồm trong các vòng tròn khác là con của những vòng tròn lớn hơn). Cả hai hoạt động mất O(n^2)ở mức tồi tệ nhất và O(n log n)tốt nhất. Sau đó, tôi lặp qua cây để đếm các khu vực. Nếu con của một vòng tròn lấp đầy toàn bộ đường kính của nó, có hai khu vực mới, nếu không thì chỉ có một. Lặp đi lặp lại này O(n). Vì vậy, tôi có sự phức tạp tổng thể O(n^2)và đủ điều kiện cho cả phần thưởng và hình phạt.

Mã này hy vọng đầu vào không có số lượng vòng tròn sẽ được lưu trữ trong một biến 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

Phiên bản Ungolfed (dự kiến ​​đầu vào biến 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. vâng, trường hợp thử nghiệm sẽ tốt đẹp. Mối quan hệ xác định các cạnh trong cây của tôi chỉ đơn giản là bao gồm một vòng tròn trong một vòng tròn khác. Vì trên vòng tròn không thể được chứa trong hai vòng tròn không chứa nhau (do điều kiện "một giao lộ"), tôi không thấy làm thế nào đây có thể là một DAG.
Martin Ender

Có phải cháu của một nút cũng là con của nó?
user2357112 hỗ trợ Monica

@ user2357112 không, bởi vì họ chỉ có thể chia tay cha mẹ trực tiếp của mình
Martin Ender

@NiklasB. Nếu tôi chạy nó với ví dụ trong câu hỏi của bạn, tôi nhận được 11. Đối với một trong nhận xét của bạn 9.
Martin Ender

@NiklasB. chờ đợi, tôi thực sự nhận được 108với phiên bản ungolfed của tôi, nhưng 119với phiên bản của tôi hiện tại golfed: D
Martin Ender

2

Ruby, 203 183 173 133 - 100 = 33 ký tự

Vì vậy, đây là một cách tiếp cận khác nhau. Lần này, tôi sắp xếp các vòng tròn theo điểm ngoài cùng bên trái của chúng. Các vòng tròn chạm vào điểm cực trái của chúng được sắp xếp từ lớn nhất đến nhỏ nhất. Điều này cần O(n log n)(tốt, Ruby sử dụng sắp xếp nhanh, vì vậy thực tế O(n^2)nhưng việc thực hiện sắp xếp hợp nhất / heap có lẽ nằm ngoài phạm vi của thách thức này). Sau đó, tôi lặp lại danh sách này, ghi nhớ tất cả các vị trí ngoài cùng bên phải và bên phải nhất của các vòng tròn tôi đã truy cập. Điều này cho phép tôi phát hiện nếu một loạt các vòng tròn kết nối tất cả các cách trên một vòng tròn lớn hơn bao quanh. Trong trường hợp này, có hai subareas, nếu không chỉ là một. Lặp lại này chỉ O(n)đưa ra tổng số phức tạp O(n log n)đủ điều kiện nhận phần thưởng 100 ký tự.

Đoạn mã này hy vọng đầu vào sẽ được cung cấp thông qua một tệp trong các đối số dòng lệnh mà không có số lượng vòng tròn:

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

Phiên bản Ungolfed (dự kiến ​​đầu vào trong một biến 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

Thật không may, điều này không thành công cho tất cả các testcase lớn hơn. Mặc dù vậy, nó rất nhanh;) Lần này tôi không có một ví dụ thất bại nhỏ, nhưng bạn có thể tìm thấy dữ liệu thử nghiệm trên trang web của cuộc thi mà tôi đã liên kết (đó là cuộc thi số 6)
Niklas B.

Testcase thất bại đầu tiên là kruznice / kruznice.in.2, đây là trường hợp thử nghiệm "thực" đầu tiên, vì vậy tôi cho rằng có một cái gì đó sai về cơ bản làm hỏng thuật toán hoặc thực hiện. Liệu nó hoạt động chính xác với các vòng tròn lồng nhau tùy ý?
Niklas B.

@NiklasB. cảm ơn, tôi sẽ xem xét các trường hợp thử nghiệm (có thể đưa tôi đến tối mai để sửa nó)
Martin Ender

@NiklasB. Tôi đã tìm ra vấn đề và ví dụ thất bại tối thiểu cần 5 vòng tròn : -1 1 1 1 0 2 4 2 0 6. Tôi sẽ suy nghĩ về cách khắc phục điều này vào tối mai (hy vọng).
Martin Ender

Phân tích phức tạp của bạn dường như cho rằng truy cập mảng kết hợp là thời gian không đổi. Điều đó dường như không thể đúng trong trường hợp xấu nhất.
Peter Taylor

1

Julia - 260 -100 (tiền thưởng?) = 160

Giải thích các vòng tròn dưới dạng hình với các đỉnh (giao điểm), cạnh và mặt (diện tích của mặt phẳng) chúng ta có thể liên kết với nhau bằng đặc tính Euler , vì vậy chúng ta chỉ cần biết số lượng "đỉnh" và "cạnh" để có số của "các mặt" hoặc các vùng của mặt phẳng với công thức được viết dưới đây:Đặc tính Euler

CẬP NHẬT: Bằng cách suy nghĩ một lúc tôi đã phát hiện ra rằng vấn đề với phương pháp của tôi chỉ là khi các vòng tròn không được kết nối, vì vậy tôi đã đưa ra một ý tưởng, tại sao không kết nối chúng một cách giả tạo? Vì vậy, toàn bộ sẽ đáp ứng công thức Euler.

Ví dụ về vòng kết nối

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

[Không làm việc với các vòng tròn lồng nhau, vì vậy đây không phải là câu trả lời cho vấn đề chung]

Mã số :

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

Tôi nghĩ rằng chương trình của bạn sẽ thất bại cho 2 -10 1 10 1.
Niklas B.

"Nó được đảm bảo rằng không có cặp vòng tròn nào có nhiều hơn một điểm chung." vì vậy tôi nghĩ rằng nó sẽ không được áp dụng :)
ĐCSTQ

@CCP Họ không có điểm chung. n=2, các vòng tròn là (C=(-10,0), r=1)(C=(10,0), r=1)
Niklas B.

1
Không phải biểu đồ phải được kết nối để áp dụng đặc tính Euler?
user2357112 hỗ trợ Monica

1
À, đây là một trường hợp đơn giản: 4 0 2 1 1 10 2 11 1Nhưng tôi không nghĩ rằng tôi có thể cung cấp cho bạn nhiều trường hợp thử nghiệm hơn, điều đó sẽ hơi bất công
Niklas B.

1

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

Tôi nghĩ rằng nếu tôi viết lại cái này trong Ruby hoặc Python thì tôi có thể lưu các ký tự.

Mã số:

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)

Thuật toán:

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

Tôi không tuyệt vời lắm với ký hiệu O lớn, nhưng tôi nghĩ đó là O (n) vì tôi thực sự lặp qua mỗi vòng tròn 3 lần (tạo, trái, phải) và cũng sắp xếp các phím của bản đồ (và tôi sắp xếp cho O ( n log n) nhưng điều đó biến mất). Đây có phải là quyết định?


Nếu bất cứ ai có lời khuyên về cách kết hợp rvòng lặp và lvòng lặp thành một tuyên bố, tôi sẽ đánh giá cao nó.
Không phải Charles

Chúc mừng :) Có vẻ như thời gian chạy của bạn thực sự là O (n log n), do sắp xếp, sẽ là -100. Tôi sẽ cho bạn biết liệu nó có vượt qua tất cả các trường hợp thử nghiệm hay không.
Niklas B.

Thật tuyệt, chương trình của bạn vượt qua tất cả các trường hợp thử nghiệm trong lần thử đầu tiên. Tôi nghĩ một cái gì đó như thế này (đường quét với một số trạng thái được duy trì trong một ngăn xếp) là giải pháp chính thức từ các tác giả vấn đề. Chương trình của bạn nhận được tổng số điểm là 173
Niklas B.

@NiklasB. Cảm ơn!
Không phải Charles

Tôi đã thử một giải pháp mạnh mẽ hơn nhiều với các vòng tròn chồng chéo .... sau đó tôi thấy rằng chúng chỉ có thể giao nhau tại một điểm.
Không phải Charles

-1

JavaScript (ES6) - 255 254 ký tự - 100 250 tiền thưởng = 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

Giả sử rằng chuỗi đầu vào nằm trong biến Svà xuất số lượng vùng cho bàn điều khiển.

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).

Độ phức tạp thời gian bây giờ là O (N).

Trường hợp kiểm tra 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

Đầu ra: 3

Trường hợp thử nghiệm 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

Đầu ra: 5

Trường hợp thử nghiệm 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

Đầu ra: 6

Trường hợp thử nghiệm 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

Đầu ra: 11

Trường hợp thử nghiệm 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

Đầu ra: 105

Phiên bản trước

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

Với nhận xét:

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).

Độ phức tạp tổng thời gian là O (N) cho tất cả mọi thứ ngoại trừ loại là O (N.log (N)) - tuy nhiên thay thế bằng loại sắp xếp xô, điều này sẽ làm giảm tổng độ phức tạp thành O (N).

Bộ nhớ cần có là O (N).

Đoán xem điều gì tiếp theo trong danh sách việc cần làm của tôi ... sắp xếp xô dưới 150 ký tự. Làm xong


Bucket loại chỉ có độ phức tạp trung bình O(n)(trên thực tế O(n+k)), nhưng O(n^2)hoặc O(n log n)trường hợp xấu nhất tùy thuộc vào các thuật toán sắp xếp được sử dụng trong xô, vì vậy bạn sẽ cần phải làm điều đó trong 50 ký tự.
Martin Ender

@ m.buettner - Sắp xếp nhóm có thể được thực hiện trong độ phức tạp trong trường hợp xấu nhất O (N). Nó dựa vào sự lựa chọn cẩn thận của các nhóm và thuật toán O (1) để gán cho các nhóm. Tôi đã làm điều đó trước đây (và đã chứng minh điều đó) và tôi chỉ cần chuyển mã sang JavaScript. Thuật toán ở trên đã là O (N.log (N)), vì vậy cải tiến duy nhất là có được thuật toán sắp xếp O (N).
MT0

Tôi sẽ quan tâm đến bằng chứng đó và sự lựa chọn tương ứng của xô. :)
Martin Ender

cs.princeton.edu/~dpd/Papers/SCG-09-invited/iêu (trên trang 556) đưa ra ví dụ về loại xô O (N). archive.org/stream/PlanarityTestingByPathAddition/ cấp (trang 75) đưa ra một ví dụ về tìm kiếm DFS kết hợp O (N) và sắp xếp xô (độ phức tạp thời gian được thảo luận trên trang 76).
MT0

1
@ Mt0 giữ ở đó, bạn có thể đọc phần bổ sung của tôi vào phần phức tạp của câu hỏi. Với các số không giới hạn, việc sắp xếp theo thời gian tuyến tính chắc chắn là không thể
Niklas B.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.