Sắp xếp chồng sách


21

Khi xếp sách bạn thường muốn đặt những cuốn lớn nhất ở dưới cùng và những cuốn nhỏ nhất ở trên cùng. Tuy nhiên, OCD tiềm ẩn của tôi khiến tôi cảm thấy rất khó chịu nếu tôi có hai cuốn sách trong đó một cuốn ngắn hơn (chiều cao) nhưng rộng hơn cuốn kia. Bất kể tôi đặt chúng theo thứ tự nào, cuốn sách hàng đầu sẽ mở rộng ra ngoài cuốn sách dưới cùng ở một bên.

Ví dụ: giả sử một cuốn sách có kích thước (10,15)và cuốn sách khác có kích thước (11,14). Bất kể cách nào tôi đặt chúng, tôi đều có phần nhô ra. Nhưng nếu tôi có những cuốn sách có kích thước (4,3)(5,6), tôi có thể tránh được phần nhô ra bằng cách đặt cái sau bên dưới cái trước.

Đối với mục đích của thử thách này, chúng tôi sẽ xem xét phần nhô ra chỉ liên quan đến cuốn sách ngay bên dưới . Ví dụ: nếu tôi có một ngăn xếp (5,5),(3,3) , (4,4)(không phải là bất kỳ người nào lành mạnh sẽ làm điều đó), đếm cuốn sách đầu như một nhô ra, mặc dù nó không mở rộng ra ngoài những cuốn sách dưới. Tương tự, ngăn xếp (3,3), (3,3), (4,4)cũng chỉ có một nhô ra, mặc dù cuốn sách đầu vượt ra ngoài một đáy.

Các thách thức

Đưa ra một danh sách các cặp số nguyên cho kích thước sách, sắp xếp các cặp / sách đó sao cho số lượng phần nhô ra là tối thiểu. Bạn không được xoay sách - Tôi muốn tất cả các gai quay về cùng một hướng. Nếu có nhiều giải pháp có cùng số lượng nhô ra, bạn có thể chọn bất kỳ thứ tự nào như vậy. Thuật toán sắp xếp của bạn không cần phải ổn định. Việc triển khai của bạn có thể cho rằng kích thước sách nhỏ hơn 2 16 mỗi .

Độ phức tạp thời gian: Để làm cho điều này thú vị hơn một chút, độ phức tạp trong trường hợp xấu nhất của thuật toán của bạn phải là đa thức về kích thước của ngăn xếp. Vì vậy, bạn không thể kiểm tra mọi hoán vị có thể. Vui lòng bao gồm một bằng chứng ngắn về tính tối ưu và độ phức tạp của thuật toán của bạn và tùy ý một âm mưu hiển thị tỷ lệ cho các đầu vào ngẫu nhiên lớn. Tất nhiên, bạn không thể sử dụng kích thước tối đa của đầu vào làm đối số mà mã của bạn chạy trong O (1).

Bạn có thể viết chương trình hoặc hàm, nhận đầu vào qua STDIN, ARGV hoặc đối số hàm theo bất kỳ định dạng danh sách thuận tiện (không được xử lý trước) và in hoặc trả về kết quả.

Đây là mã golf, vì vậy câu trả lời ngắn nhất (tính bằng byte) sẽ thắng.

Tôi tin tưởng rằng một giải pháp đa thức tồn tại, nhưng nếu bạn có thể chứng minh tôi sai, bạn có thể gửi bằng chứng như vậy thay vì nộp bài đánh gôn. Trong trường hợp này, bạn có thể giả sử P ≠ NP . Tôi sẽ chấp nhận bằng chứng chính xác đầu tiên và trao tiền thưởng cho nó.

Ví dụ

In:  [[1, 1], [10, 10], [4, 5], [7, 5], [7, 7], [10, 10], [9, 8], [7, 5], [7, 5], [3, 1]]
Out: [[10, 10], [10, 10], [9, 8], [7, 7], [7, 5], [7, 5], [7, 5], [4, 5], [3, 1], [1, 1]]

In:  [[4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [5, 4], [4, 5]]
Out: [[4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [5, 4]]
  or [[5, 4], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5]]

In:  [[2, 3], [1, 1], [5, 5], [7, 1]]
Out: [[5, 5], [2, 3], [7, 1], [1, 1]]
 or  [[5, 5], [2, 3], [1, 1], [7, 1]]
 or  [[7, 1], [5, 5], [2, 3], [1, 1]]
 or  [[7, 1], [1, 1], [5, 5], [2, 3]]

Tôi đã tạo ra những thứ này bằng tay, vì vậy hãy cho tôi biết nếu bạn phát hiện ra bất kỳ sai lầm nào.


3
Bạn có chắc chắn rằng việc tìm một giải pháp với số lượng nhô ra tối thiểu có thể được giải quyết trong thời gian đa thức?
COTO

@COTO Tôi khá tự tin, vâng.
Martin Ender

Hừm. Tôi thường giải quyết nó bằng thuật toán tham lam, nhưng tôi có thể dễ dàng mua các đầu vào dẫn đến đầu ra dưới mức tối ưu cho bất kỳ tiêu chí "tham lam" nào tôi có thể đưa ra (ví dụ: diện tích, tối đa hóa một chiều, tối đa hóa kích thước nhỏ nhất, v.v.). Các cách tiếp cận khác mà tôi có thể nghĩ đến liên quan đến việc phân chia các cuốn sách thành các cụm, và tất cả chúng đều có độ phức tạp trong trường hợp xấu nhất theo cấp số nhân. Tôi sẽ quan tâm để xem những gì câu trả lời đi lên. Bạn cũng có thể muốn yêu cầu một bằng chứng ngắn gọn về sự tối ưu của loại như là một phần của thông số kỹ thuật.
COTO

@COTO Tôi đã thêm một đoạn về điều này trong trường hợp tôi thực sự sai, nhưng đừng tin vào điều đó. ;)
Martin Ender

Trong trường hợp, bằng chứng tiềm năng rằng không có thuật toán đa thức thời gian tồn tại nên được phép cho rằng P không bằng NP.
xnor

Câu trả lời:


2

Bình thường , 30

FN_SQFbYIgeeYeb~b]NB)E~Y]]N;sY

Đây là một golf trực tiếp của thuật toán tuyệt vời của grc. Đây là tương đương chính xác của chương trình pyth ở trên, trong mã python được biên dịch của nó.

Q = eval(input())
Y = []
for N in sorted(Q)[::-1]:
     for b in Y:
         if Y[-1][-1] >= b[-1]:
             b += [N]
             break
     else:
         Y += [[N]]
print(Psum(Y))

Trong bối cảnh này, Psum(Y)chức năng tương đương với con trăn sum(Y,[]).

Mã biên dịch và chạy thực tế (từ pyth -d):

Y=[]
Q=copy(eval(input()))
for N in neg(Psorted(Q)):
 for b in Y:
  if gte(end(end(Y)),end(b)):
   b+=[N]
   break
 else:
  Y+=[[N]]
Pprint("\n",Psum(Y))

1
Bản dịch Python cần "Y = []", xóa eval nếu bạn ở trong Python 2 và tổng cần một đối số thứ hai sum(Y,[]). Tất cả điều này sẽ hoạt động trong Pyth, chỉ là bản dịch không tự động bao gồm nó.
xnor

@xnor Dòng cuối cùng thực sự đọc : Pprint("\n",Psum(Y)). Tôi nghĩ rằng anh ta có thể đã đơn giản hóa nó để thuận tiện, cùng với tất cả các -1vv vv Psumthực sự sẽ chạy nhiều hơn như thế reduce(lambda x,y:x+y, Y[1:], Y[0]).
FryAmTheEggman

20

Con trăn, 113

P=[]
for n in sorted(input())[::-1]:
 for p in P:
  if p[-1][1]>=n[1]:p+=[n];break
 else:P+=[[n]]
print sum(P,[])

Sau khi sắp xếp danh sách các cuốn sách theo thứ tự giảm dần (theo chiều rộng trước rồi chiều cao), phần này sẽ phân chia các cuốn sách thành đống mà không chồng chéo. Để xác định nơi đặt mỗi cuốn sách, chiều cao của nó được so sánh với chiều cao của cuốn sách trên cùng trong mỗi đống. Nó được đặt trên cọc đầu tiên có thể, nếu không thì một cọc mới được tạo ra.

Tôi không giỏi lắm với độ phức tạp của thời gian, nhưng tôi tin rằng nó sẽ có trường hợp xấu nhất là O ( N 2 ). Có hai vòng lặp, mỗi vòng có nhiều nhất N lần lặp. Tôi cũng sử dụng sắp xếp dựng sẵn của Python, đó là O ( n log n ).


Bằng chứng đầu tiên của tôi rằng thuật toán này tạo ra các giải pháp tối ưu hóa ra không chính xác. Một lời cảm ơn rất lớn đến @xnor và @ Sp3000 cho một cuộc thảo luận tuyệt vời trong cuộc trò chuyện về việc chứng minh điều này (mà bạn có thể đọc bắt đầu từ đây ). Sau khi đưa ra một bằng chứng chính xác, @xnor thấy rằng một phần của nó đã được thực hiện ( định lý của Dilworth ).

Dưới đây là tổng quan về bằng chứng (ghi có vào @xnor và @ Sp3000).

Đầu tiên, chúng tôi định nghĩa khái niệm về một chất chống mồ hôi, hoặc antichain, ( trích từ @xnor ):

Một antipile là một chuỗi các cuốn sách có chiều cao giảm dần, nhưng tăng chiều rộng
Vì vậy, mỗi cuốn sách kế tiếp đều cao hơn nhưng không quá rộng
Lưu ý rằng bất kỳ cuốn sách nào trong một antipile nhô ra trên bất kỳ cuốn sách nào khác trong một antipile
Vì vậy, không có hai cuốn sách trong một antipile
Do đó, trong cùng một đống Do đó, nếu bạn có thể tìm thấy một antipile của x sách, thì những cuốn sách đó phải ở các cọc khác nhau
Vì vậy, kích thước của antipile lớn nhất là giới hạn thấp hơn về số lượng cọc

Sau đó, chúng tôi sắp xếp các cuốn sách theo thứ tự giảm dần theo chiều rộng của chúng (thứ nhất) và chiều cao của chúng (thứ hai) *.

Đối với mỗi cuốn sách B , chúng tôi làm như sau:

  1. Nếu B có thể vừa với đống đầu tiên, chúng ta đặt nó ở đó và di chuyển tiếp.
  2. Mặt khác, chúng tôi tìm thấy * cọc x sớm nhất mà B có thể được đặt lên trên cùng. Đây có thể là một đống mới nếu cần thiết.
  3. Tiếp theo, chúng tôi liên kết B đến P , trong đó P là cuốn sách hàng đầu trên cọc trước x - 1 .
  4. Bây giờ chúng ta biết rằng:
    • B hoàn toàn * nhỏ hơn chiều rộng so với P , vì các sách được sắp xếp theo thứ tự giảm dần theo chiều rộng
    • B có chiều cao lớn hơn P , hoặc chúng ta sẽ đặt B lên trên P

Bây giờ, chúng tôi đã xây dựng một liên kết từ mỗi cuốn sách (ngoại trừ những cuốn trong đống đầu tiên), đến một cuốn sách trong đống trước đó có chiều rộng lớn hơn và chiều cao thấp hơn.

Sơ đồ tuyệt vời của @ Sp3000 minh họa rõ điều này:

Bằng cách đi theo bất kỳ con đường nào từ đống cuối cùng (bên phải), đến đống đầu tiên (bên trái), chúng ta sẽ có được một chất chống mồ hôi. Điều quan trọng, chiều dài của antipile này bằng với số lượng cọc. Do đó, số lượng cọc được sử dụng là tối thiểu.

Cuối cùng, vì chúng tôi đã sắp xếp các cuốn sách thành số lượng cọc tối thiểu mà không bị chồng chéo, chúng tôi có thể xếp chồng chúng lên nhau để có được một đống với số lượng chồng chéo tối thiểu.

* bình luận hữu ích này giải thích một vài điều


3
+1 cho bằng chứng tiếp xúc và liên kết đến cuộc thảo luận. Đạo cụ cho xnor et al.
COTO

Tôi nên làm rõ rằng Định lý của Dilworth không bao gồm toàn bộ bằng chứng, thực tế là số lượng cọc nhỏ nhất bằng với chất chống kích cỡ lớn nhất.
xnor
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.