Farklı boyutlardaki dikdörtgenleri mümkün olan en küçük dikdörtgene paketlemek için hangi algoritma kullanılabilir?


273

Mümkün olan en küçük alana paketlemem gereken bir grup dikdörtgen nesnem var (bu alanın boyutları iki güç olmalı).

Belirli bir alana mümkün olduğu kadar öğeleri paketleyecek çeşitli paketleme algoritmalarının farkındayım, ancak bu durumda bu alanın ne kadar büyük olması gerektiğini anlamak için algoritmaya ihtiyacım var.

Örneğin, aşağıdaki dikdörtgenlere sahip olduğumu söyle

  • 128 * 32
  • 128 * 64
  • 64 * 32
  • 64 * 32

128 * 128 alana paketlenebilirler

 _________________
| 128 * 32 |
| ________________ |
| 128 * 64 |
| |
| |
| ________________ |
| 64 * 32 | 64 * 32 |
| _______ | ________ |

Bununla birlikte, 160 * 32 ve 64 * 64 bir alan da olsaydı, 256 * 128 alan gerekirdi

 ________________________________
| 128 * 32 | 64 * 64 | 64 * 32 |
| ________________ | | _______ |
| 128 * 64 | | 64 * 32 |
| | _______ | _______ |
| | |
| ________________ | ___ |
| 160 * 32 | |
| ____________________ | ___________ |

Bir grup dikdörtgeni paketleyebilen ve kap için gerekli boyutu belirleyebilen hangi algoritmalar var (2 güçte ve her boyut için belirli bir maksimum boyutta)?


6
İkinci çözüm uygun değil mi? 128 x 224 olmamalı mı?
Mantas Vidutis

"Bu alanın boyutları iki güç olmalıdır" Bu yüzden hiçbir fark yaratmaz, bunun için ne olduğu için iki güç olmayan temel donanım tarafından koşulsuz destekli olduğunu varsayamıyorum.
Ateş Lancer

2
Neyse sonunda algoritma kolaylaştı :) (nto sonra 64x32 sonra 64x64, 128x64 vb çalışırsanız, 32x32 hepsini sığdırmak için deneyin)
Yangın Lancer


Buraya bir tür kaba kuvvet çözümü koydum stackoverflow.com/a/47698424/1641247
Sean

Yanıtlar:


67

Hızlı ve kirli ilk geçiş çözümü her zaman başlamak için harika bir çözümdür, başka bir şey yoksa bir karşılaştırma olarak.

Büyükten küçüğe açgözlü yerleşim.

Kalan en büyük dikdörtgeni paketlenmiş alanınıza koyun. Hiçbir yere sığmazsa, paket bölgesini mümkün olduğunca az uzatacak bir yere yerleştirin. En küçük dikdörtgeni bitinceye kadar tekrarlayın.

Hiç mükemmel değil ama kolay ve güzel bir temel. Orijinal örneğinizi mükemmel bir şekilde paketleyecek ve ikincisi için de eşdeğer bir cevap verecektir.


1
Biraz kağıt üzerinde böyle bir şeyle oynuyordum, şu anda çoğu durumda, dikdörtgenleri veya herhangi bir şeyi döndürmeden bile oldukça uygun görünüyor
Fire Lancer

1
Onu uyguladım ve bir sürü test verisi çalıştırdım, sadece biraz israf veri bırakarak oldukça iyi bir iş yapıyor gibi görünüyor. Şimdi, her piksel kontrol edilebilir kullanılabilir alan üzerinden her rekt için doğrusal bir arama daha verimli olmak için benim uygulama yeniden yazmak gerekir nokta (mevcut tüm rect karşı) bloke olduğunu ...
Yangın Lancer


2
Bunun ne kadar optimal olabileceğini hayal etmeye çalışırken zorlandım. Bu yüzden (kare şeklinde) kodladım ve sonuçlar harika. İşte bir demo animasyon: imgur.com/ISjxuOR
Attila Tanyi

@JimBalter kare alanı akıllıca ... muhtemelen ... hız ve ölçeklenebilirlik açısından? Pek sayılmaz?
Arek Bal

86

Çözümlerin bir araştırması için ARC projesinde bu sayfaya bakın , uygulama karmaşıklığı / zamanı ve optimallik arasında bir denge var, ancak seçim için çok çeşitli algoritmalar var.

İşte algoritmaların bir özeti:

  1. İlk Takılma Azalan Yükseklik (FFDH) algoritması
    FFDH, R'nin uyduğu ilk seviyedeki bir sonraki R (artan yükseklikteki) öğeyi paketler. Hiçbir seviye R'yi barındıramazsa, yeni bir seviye oluşturulur.
    FFDH'nin zaman karmaşıklığı: O (n · log n).
    Yaklaşıklık oranı: FFDH (I) <= (17/10) · OPT (I) +1; 17 / 10'un asimptotik sınırı sıkıdır.

  2. Next-Fit Azalan Yükseklik (NFDH) algoritması
    NFDH, R uyuyorsa bir sonraki R öğesini (artan yükseklikte) geçerli seviyeye paketler. Aksi takdirde, geçerli seviye "kapalı" olur ve yeni bir seviye oluşturulur.
    Zaman karmaşıklığı: O (n · log n).
    Yaklaşıklık oranı: NFDH (I) <= 2 · OPT (I) +1; 2'nin asimptotik sınırı sıkıdır.

  3. En Uygun Azaltma Yüksekliği (BFDH) algoritması
    BFDH, kalan yatay boşluğun minimum olduğu R'yi barındırabilenler arasında bir sonraki R öğesini (artan yükseklikte) paketler. Hiçbir seviye R'yi barındıramazsa, yeni bir seviye oluşturulur.

  4. Sol Alt (BL) Algoritma
    BL artan sipariş genişliğine göre birinci dereceden eşyalar. BL, bir sonraki öğeyi sığacak kadar dibe yakın ve daha sonra herhangi bir paketlenmiş öğeyle örtüşmeden gidebildiği kadar sola yakın paketler. BL'nin seviye odaklı bir paketleme algoritması olmadığını unutmayın.
    Zaman karmaşıklığı: O (n ^ 2).
    Yaklaşıklık oranı: BL (I) <= 3 · OPT (I).

  5. Fırıncı Yukarı-Aşağı (UD) algoritması
    UD, BL'nin bir kombinasyonunu ve NFDH'nin genelleştirilmesini kullanır. Şeridin genişliği ve parçaları, şerit birim genişliği olacak şekilde normalleştirilir. UD, öğeleri genişlemeyen genişlikte sipariş eder ve ardından her biri genişliği (1/2, 1], (1 / 3,1 / 2], (1 / 4,1 / 3 aralığında olan öğeleri beş gruba böler. ], (1 / 5,1 / 4], (0,1 / 5]. Şerit ayrıca beş bölgeye ayrılır R1, ···, R5. Temel olarak, aralıktaki bazı genişlik öğeleri (1 / i + 1, 1 / i], 1 <= i <= 4 için, BL tarafından Ri bölgesine paketlenir BL, şeridin sağ tarafında yukarıdan aşağıya doğru artan bir boşluk bıraktığından, UD önce bu avantajı alır öğeyi yukarıdan aşağıya doğru j = 1, ···, 4 (sırayla) için Rj'ye paketleme Böyle bir alan yoksa, öğe BL tarafından Ri'ye paketlenir.Nihayet, en fazla 1/5 boyutunda öğeler (genelleştirilmiş) NFDH algoritması ile R1, ···, R4'teki alanlara paketlenir.
    Yaklaşıklık oranı: UD (I) <= (5/4) · OPT (I) + (53/8) H, burada H, öğelerin maksimum yüksekliğidir; 5/4 asimptotik sınırı sıkıdır.

  6. Ters takma (RF) algoritması
    RF ayrıca şeridin ve öğelerin genişliğini normalleştirir, böylece şerit birim genişliğinde olur. RF, ilk önce genişliği 1 / 2'den büyük tüm parçaları istifler. Kalan öğeler artmayan yükseklikte sıralanır ve 1/2'den büyüklerin ulaştığı H0 yüksekliğinin üzerinde paketlenir. Ardından RF aşağıdaki işlemi tekrarlar. Kabaca konuşursak, RF, yer kalmayıncaya kadar öğeleri soldan sağa H0 yükseklik çizgisi boyunca paketler. Ardından, toplam genişlik en az 1/2 olana kadar öğeleri sağdan sola ve yukarıdan aşağıya (ters düzey denir) paketler. Ardından, ters seviye (en azından) biri aşağıdaki öğelere değene kadar düşürülür. Açılır menü bir şekilde tekrarlanır.
    Yaklaşıklık oranı: RF (I) <= 2 · OPT (I).

  7. Steinberg'in algoritması
    Steinberg'in algoritması, kağıtta M olarak ifade edilir, tüm öğelerin paketlenmesi için gereken H yüksekliğinin üst sınırını tahmin eder, böylece giriş öğelerinin W ve H genişliğinde bir dikdörtgen içine paketlenebileceği kanıtlanır. her biri bir problemi iki küçük soruna bölmek ve bunları özyinelemeli olarak çözmek için yedi prosedür (yedi koşullu) tanımlayın. İzlenebilir herhangi bir sorunun yedi koşuldan birini karşıladığı gösterilmiştir.
    Yaklaşıklık oranı: M (I) <= 2 · OPT (I).

  8. Split-Fit algoritması (SF) SF, öğeleri iki gruba ayırır, L1 genişliği 1/2'den büyük ve L2 en fazla 1/2. L1'in tüm öğeleri ilk önce FFDH tarafından paketlenmiştir. Daha sonra, genişliği 2/3'ten fazla olan tüm öğeler, genişliği en fazla 2/3 olanların altında olacak şekilde düzenlenir. Bu, 1/3 genişliğinde bir dikdörtgen R alanı oluşturur. Daha sonra L2'de kalan öğeler R'ye paketlenir ve FFDH kullanılarak L1 ile paketlenenlerin üzerindeki boşluk paketlenir. R'de yaratılan seviyelerin, L1 ambalajının üzerinde yaratılan seviyelerin altında olduğu kabul edilir.
    Yaklaşıklık oranı: SF (I) <= (3/2) · OPT (I) + 2; 3/2 asimptotik bağ sıkıdır.

  9. Sleator algoritması
    Sleater algoritması dört adımdan oluşur:

    1. 1/2 'den daha büyük tüm eşyalar, şeridin alt kısmında üst üste yerleştirilir. H0'ın sonuçta ortaya çıkan paketin yüksekliği olduğunu varsayalım Sonraki tüm paketleme h0'ın üzerinde gerçekleşecektir.

    2. Kalan öğeler artan yükseklikle sipariş edilir. H0 yükseklik çizgisi boyunca soldan sağa doğru bir miktar öğe (artan yükseklik sırasına göre) paketlenir.

    3. Daha sonra şeridi iki eşit yarıya kesmek için ortada dikey bir çizgi çizilir (bu çizginin kısmen sağ yarısında paketlenmiş bir öğeyi kesebileceğini unutmayın). İki satır herhangi bir öğeyi geçmeyecek şekilde, bir yarısı sol yarıya (sol taban çizgisi denir) ve bir sağ yarıya (sağ taban çizgisi denir) uzunluğunda iki yatay çizgi parçası çizin.

    4. Daha düşük bir yüksekliğe sahip sol veya sağ taban çizgisini seçin ve bir sonraki öğe çok geniş olana kadar şeridin ilgili yarısına bir seviye öğe paketleyin.

    Yeni bir taban çizgisi oluşturulur ve tüm maddeler paketlenene kadar Adım (4) alt taban çizgisinde tekrarlanır.
    Zaman karmaşıklığı: O (n · log n).
    Sleator algoritmasının yaklaşık oranı 2,5'tir ve bu da sıkıdır.


6
Tüm bunlar, alanın genişliğini bilmeyi gerektirir.
Quantum7

1
@ Quantum7 muhtemelen çok önemli değil, çünkü OP iki tarafın gücü olmasını gerektiriyor, bu yüzden yeterli alana sahip bir sürü boyutu deneyebiliriz.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

19

Paketleme sorunlarına bir göz atın . Bence seninki '2D kutu ambalajı' altına giriyor. Buna ve diğer paketleme sorunlarına çözümlerden çok şey öğrenebilmelisiniz.

Ayrıca bkz: Dikdörtgen görüntü verilerini kare bir dokuya paketleme.


İşte optimize eden bir dikdörtgen paketleme algoritmasının güzel bir örneği: codeproject.com/Articles/210979/…
Anderson Green

Sorun ayrıca şu şekilde de belirtilmiştir: en.wikipedia.org/wiki/… Özellikle, bin ambalajı bilinmeyen boyuttaki tek bir bölmeye sınırlar, hala NP-tamamlanmış olup olmadığını merak ediyorum.
Ciro Santilli

17

Bu sorunla ilgili kapsamlı literatür var. İyi bir açgözlü sezgisel tarama, kabın dibine ve soluna doğru mevcut ilk konumda en büyük alandan en küçüğe dikdörtgenler yerleştirmektir. Tüm öğeleri sol alt köşeye çekerek yerçekimini düşünün. Bu google "Chazelle alt sol ambalaj" bir açıklama için.

En iyi çözümler için, en yeni teknikler birkaç saniyede 20'den fazla dikdörtgen paketleyebilir. Huang, en küçük çevreleyen sınırlayıcı kutuyu bulma sorununu, bir dikdörtgen kümesinin belirli bir boyuttaki sınırlayıcı kutuya sığıp sığmayacağına karar verme sorunundan ayıran bir algoritmaya sahiptir . Programına bir dikdörtgen kümesi veriyorsunuz ve size bunları paketlemek için gereken en küçük sınırlayıcı kutuyu anlatıyor.

Sizin durumunuz için, dış döngünüz mümkün olan en küçük sınırlayıcı kutudan yukarı doğru yinelenmelidir (genişlik ve yükseklik art arda iki güçle artar). Bu sınırlayıcı kutuların her biri için, dikdörtgenleriniz için bir ambalaj bulup bulamayacağınızı test edin. En iyi çözüm olduğu garanti edilen ilk "evet" cevabına kadar bir grup "hayır" yanıtı alacaksınız.

Algoritmanızın iç döngüsü için - belirli boyuttaki sınırlayıcı bir kutuya "evet" veya "hayır" yanıtını veren kişi için, Huang referansını arar ve algoritmasını uygularım. Temel algoritmanın üstünde birçok optimizasyon içeriyor, ancak sadece temel et ve patateslere ihtiyacınız var. Döndürme işlemlerini yapmak istediğiniz için, aramanız sırasında her dallanma noktasında, her iki döndürme de bir çözümle sonuçlanmadığında, hem döndürmeyi hem de geriye doğru izlemeyi deneyin.


9

Bunun NP zor bir sorun olduğundan oldukça eminim, bu nedenle en uygun çözüm için olası her kombinasyonu deneyen bir geri izleme algoritması uygulamanız gerekir.

İyi haber şu ki, 2D dikdörtgenleri sınırlı bir 2D alanda paketleme ihtiyacı nedeniyle, çok sayıda olasılığı erken budayabilirsiniz, bu yüzden bu kötü olmayabilir.


3
Muhtemelen NP tam demek istediniz.
starblue

7
Eğer NP tamamlanmışsa, o zaman çözmek kolaydır, sadece seyahat eden satıcıların eşdeğer bir örneğini çözün ve işte gidiyorsunuz. Ancak, NP-tamamlanmış problemlerin karar problemleri (evet / hayır cevaplarını geri alırsınız) olduğundan ve polinom zaman doğrulama algoritmasına sahip olduklarından, pozlandığı gibi olmadığını göstermek önemsizdir. Soru "256 * 128'den daha az alan kaplayan a, b, c ... dikdörtgenlerinin NP-tamamlanmış olabileceğine dair bir düzenleme var mı?
Eclipse

2
@Eclipse doğru. Gönderen jair.org/media/3735/live-3735-6794-jair.pdf dikdörtgenler bir dizi belirli bir sınırlama kutu içinde paketlenmiş kullanılmayacağı karar problemi NP-tam iken "optimizasyon problemi, NP-zor çöp kutusundan indirimle (Korf, 2003). " Bununla birlikte, OP'nin "oldukça optimal bir yol" istediğini ve bunun P'de yeterince geniş "adil" tanımları için çözümler olduğunu unutmayın.
Jim Balter

NP sertliğinden de şüpheleniyorum, ancak bir referansa / kanıta ihtiyacımız var.
Ciro Santilli 法轮功 冠状 at 六四 事件 法轮功

2
Kutsal iplik necro, Batman. Bu bir paketleme problemidir ve en iyi ihtimalle NP-zor olduğu kanıtlanmıştır: en.wikipedia.org/wiki/Packing_problems
Blindy

2

İhtiyacınız olan şey https://github.com/nothings/stb/blob/master/stb_rect_pack.h adresinde

örneklem:

stbrp_context context;

struct stbrp_rect rects[100];

for (int i=0; i< 100; i++)
{
    rects[i].id = i;
    rects[i].w = 100+i;
    rects[i].h = 100+i;
    rects[i].x = 0;
    rects[i].y = 0;
    rects[i].was_packed = 0;
}

int rectsLength = sizeof(rects)/sizeof(rects[0]);

int nodeCount = 4096*2;
struct stbrp_node nodes[nodeCount];


stbrp_init_target(&context, 4096, 4096, nodes, nodeCount);
stbrp_pack_rects(&context, rects, rectsLength);

for (int i=0; i< 100; i++)
{
    printf("rect %i (%hu,%hu) was_packed=%i\n", rects[i].id, rects[i].x, rects[i].y, rects[i].was_packed);
}

1

Genel bir çözüm önemsiz değildir (matematik tamamen imkansız için konuşur)
Genellikle insanlar olası kombinasyonları denemek için genetik bir algoritma kullanırlar, ancak önce en büyük şekli koyarak ve daha sonra farklı yerler için sonraki en büyük vb.

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.