2D Dizi'de şekilleri bulma, ardından optimize etme


11

Bir görüntüye izin verildi ... Oyunumun altındaki resimde, "T" şeklinin bir parçası olarak tanınan bazı koyu renkli bloklar gösteriliyor. Görüldüğü gibi, kod kırmızı lekelerle blokları koyulaştırdı ve yeşil anahatlarla "T" şekillerini görmedi.

İstenen desenler bulundu, ancak henüz optimize edilmedi

Kodum x / y ile döngüler, blokları kullanıldığı gibi işaretler, şekli döndürür, tekrarlar, renk değiştirir, tekrarlar.

Bu kontrolü büyük bir korku ile düzeltmeye çalıştım. Şu anki fikir:

  • ızgarada döngü yapın ve tüm desen oluşumlarını not edin (blokları kullanıldığı gibi işaretlemeyin) ve bunları bir diziye koymak
  • bu kez hangi blokların hangi kalıplar tarafından işgal edildiğini ve bu nedenle birden çok kalıp tarafından işgal edildiğini not edin.
  • ızgarada tekrar dönerek, bu kez hangi kalıpların hangi kalıpları tıkadığını

Bu çok doğru geliyor ... Şimdi ne yapacağım?

Ben düşünüyorum ben olurdu

  • önce diğer desenlerin çoğunu engelleyenlerden başlayarak, birbiriyle çelişen şekillerin çeşitli kombinasyonlarını deneyin. Buna nasıl yaklaşırım?
  • 8 blok işgal eden 3 çakışan şekle sahip olduğumu ve şekillerin her biri 4 blok olduğunu söyleyen rasyonel kullanın, bu yüzden sadece maksimum iki şekle sahip olabilirim.

(Ayrıca diğer şekilleri de dahil etmeyi planlıyorum ve muhtemelen çakışan şekillerden geçerken dikkate alınması gereken skor ağırlığı olacak, ancak bu başka bir gün olabilir)

Bunun bir kutu paketleme sorunu olduğunu düşünmüyorum, ama ne arayacağından emin değilim. Umarım mantıklı, yardımın için teşekkürler

DÜZENLEME Sorunun açık olmasına rağmen, herkes anlaşılmış gibi görünüyor, evet,

Her rengin maksimum "T" şeklini bulmak istiyorum

(çünkü size iki kişilik puan verirsem ve üç tane yapmış olsaydınız, biraz sinirlenirdiniz)


Açgözlü bir algoritma, tahtayı birleştirilmiş blok koleksiyonlarına bölmek olabilir. Daha sonra her koleksiyon için ti dolgusunu şekillerle deneyebilir ve dolgunun koyulaştırılmayacak kalan blok miktarına bağlı bir puan verebilirsiniz. Beni en.wikipedia.org/wiki/Knapsack_problem hakkında düşündürüyor .
Jonathan Connell

2
Bence soruda eksik bir şey var. Mümkün olduğunca çok sayıda "T" şeklinde grup bulan bir algoritma yapmak ister misiniz?
Markus von Broady

Seni anlarsam doğru yola gidiyorsun demektir. Son derece net değilsiniz ve eğer detaylandırırsanız çok sevinirim.
AturSams

Yanıtlar:


3

Bakalım doğru anladım, kırmızı işaretli bloklar maviydi ve algoritma bir T şekli buldu ve kırmızı olarak işaretledi, doğru mu? Amacınız aynı renkli bloklarla mümkün olduğunca çok T şekli bulmak, şimdiye kadar düzeliyorum. Şu anda onları bulduktan sonra işaretleyin ve bu algoritmanın kullanışlılığını azaltır (çünkü en uygun çözümü kaçırmış olabilirsiniz). Tüm şekilleri aramayı ve sonra hangilerinin kullanılacağını ve hangilerinin kullanılmayacağını seçmeyi planlıyorsunuz. Şimdiye kadar doğru muyum? Çünkü algoritma tamamlandığında T şekillerinin içinde bulunan blok miktarını en üst düzeye çıkarmak istiyorsunuz.

Doğruysam, bence durumunuz için en uygun çözüm aşağıdadır.

Tamsayılı Doğrusal Programlamayı kullanacağız.

Geçmişte bunu kullandığımı düşünüyorum:

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(Birçok dilde çalışmasını sağlayabilirsiniz, PHP, Java ve C ile kullandım)

Yapacağımız her olası T şeklini tahtaya kaydetmek ve daha sonra kapsanan blok miktarını en üst düzeye çıkarmak için ILP'yi kullanmaktır. ILP üstel olarak karmaşıktır. Tahtanızın boyutu göz önüne alındığında, bu bir sorun olmayacaktır. ILP ile grafikler üzerinde çok daha karmaşık min / max soruları çalıştırdım ve tamamlanması sadece bir saniyenin bir kısmını ve yüzlerce köşe ile 30-90 saniyeyi aldı (sizin durumunuzda bir saniyenin bir kısmına düşüyor).

Ne tavsiye ederim:

  1. Tüm olası Çizgi şekillerini bulun
  2. Aynı renkteki çizgi şekilleri arasındaki tüm kavşakları bulun
  3. Tüm kavşakları arayarak tüm olası T şekillerini bulun.
  4. Her T şekli için Doğrusal Problemde bir Boolean değişkeni tanımlayın ( 0 <= Bi <= 1) Değerler tamsayı olduğundan, 0 veya 1 bırakır.
  5. Kesişen ( Bi + Bj <= 1) her bir T şekli için koşulları yapın
  6. Amaç işlevi ("T" Şeklindeki blokların toplamı (i) * Bi)
  7. Çözücüyü çalıştırın ve çözücünün en uygun çözümde 1 olduğu karşılık gelen Boole (ların) olduğu T şekillerini koyulaştırın.

Bu değerli bir bilgidir, iş projeleri için sıklıkla doğrusal çözücüler kullandım.

ILP temel olarak, bazı doğrusal fonksiyonlar için maksimum veya minimum ulaşmak istediğiniz seçim problemlerini çözmenin bir yoludur.

Burada daha fazla bilgi edinebilirsiniz, Tamsayı Doğrusal Programlama ve Doğrusal Programlama'yı kullanmak programcı için aynıdır, ancak Tamsayı bilgisayar için çok daha karmaşıktır ve bu da uzun çalışma sürelerine neden olabilir. Sizin durumunuzda değil, Çok basit ve en kötü durumda sadece milisaniyeden az sürmelidir.

Sanırım burada daha fazlasını okuyabilirsiniz:

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

Bu iyi açıklıyor:

http://fisher.osu.edu/~croxton_4/tutorial/

Temelde bir karar problem çözücüdür, istediğiniz sonucu en üst düzeye çıkarmak için nasıl karar vereceğinizdir. Bu, sonucu yargılanan fonksiyonun, mevcut durumunuzda doğrusal olduğunu varsayar. Bu durumda sonucu yargılayan işlev, karartmaya karar verdiğiniz tüm T şekilleri için blokları toplar.

Matematiksel olarak, değişkenler nasıl ayarlanır: mevcut durumumuzda Booleans (T şeklini i işaretini i ile indeksledim mi, etmedim mi) istediğimiz sonucu en üst düzeye çıkarmak için: kesişen T şekillerini karartmadan mümkün olduğunca çok blok karartmak. İstediğiniz sonuç, tüm değişkenleri ayarladığınızda doğrusal bir işlevle hesaplanabildiği sürece çözecektir. Bizim durumumuzda, hangi T şekillerini kararttığımızı kontrol ediyor ve kapsadıkları blokları topluyoruz.

resim açıklamasını buraya girin

Bunun önemsiz olmadığını biliyorum, bu yüzden sıçramayı seçerseniz, yorum yapmaktan çekinmeyin ve ayrıntılı olarak anlatacağım.


Yardımın için teşekkürler Arthur. Sindirmek için birkaç okuma gerekebilir. Ve evet, sorunu doğru anladın. Eğer detaylandırırsanız çok ilgilenirim (hayır, hayır önemsiz değil), ama bu gittiğim yere ulaşmama yardımcı olmalı!
Assembler

Uygulama için hangi dili kullanıyorsunuz?
AturSams

actionscript 3! herkesin favorisi!
Assembler

burada aynı. As3'te bir uygulama yazacağım ve adım adım çalışarak yorumlama için bir
github'a yükleyeceğim

Daha fazla yorum eklememi veya ayrıntılandırmamı istediğiniz 1-7 belirli alanlarınız var mı? btw, bizim için iyi haber AS3 severler, Adobe C ++ 'ı destekleyen FlasCC'yi piyasaya sürdü, böylece mevcut lineer çözücüleri kolaylıkla kullanabiliyoruz. :)
AturSams

4

Izgarada meydana gelen tüm (muhtemelen üst üste binen) T şekillerinin bir listesine sahip olduktan sonra, kalan maksimum paketleme problemidir.

Genel olarak, bu NP-tam bir sorundur. Bununla birlikte, şebekeniz kesin çözümler elde etmenin mümkün olabileceği kadar küçüktür (ve genellikle daha küçük bağımsız alt problemlere bile ayrılır).


Ek: İşte hile yapabilecek temel bir geri izleme arama algoritması:

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

Burada, {X, Y, Z}elementleri içeren bir dizi anlamına gelir X, Yve Z(ile {}boş olan) bir ve |Q|kümesinin boyutunu belirtmektedir Q.

Özyinelemeli işlevde, küme Akalan çözüm için kullanılabilir şekilleri Siçerir, geçerli çözüm adayındaki şekilleri içerir ve Mşimdiye kadarki en büyük çözümdür (geri döndürmek yerine genel değişken olarak saklamak isteyebilirsiniz çağrı zinciri). Önemli optimizasyon, // upper boundarama ağacının daha iyi bir çözüm getiremeyen dallarını budama ile işaretlenmiş satırdadır M.

(Aslında, her bir T şeklinin tam olarak dört yer içerdiğini bildiğimiz için |B|, şekillerde kapsanan B, dörde bölünmüş ve yuvarlatılmış (ve benzer şekilde |A|üzerinde) bulunan farklı yerlerin sayısıyla değiştirilerek çok daha iyi bir üst sınır elde edilebilir . çizgi ile işaretli // shortcut). algoritması, yukarıda verilen Ancak şekillerin rasgele koleksiyon çalışır gibi).

Yukarıda uygulamadığım olası bir ek optimizasyon, özyinelemeli işlevin başlangıcında, Afarklı alt kümelerde hiçbir şeklin çakışmaması ve bağımsız olarak birden çok alt kümeye bölünüp bölünmediğini kontrol etmek ve alt kümelerin her birine ayrı ayrı algoritma. (Her durumda, bunu , özyinelemeli algoritmayı çağırmadan önce kesinlikle en az bir kez en üst düzeyde yapmak istersiniz .) Şekiller Aüzerinde döngü yapmadan önce uygun şekilde sıralamak , örneğin üst üste binen şekil sayısına göre sırayla da yardımcı olabilir. .


Evet, problemin büyüklüğü nedeniyle nispeten ağrısız bir şekilde çözmek için bir ILP kullanabileceğini düşünüyorum. . Açıkça üstel olarak karmaşıktır (En azından birisi p = np'yi kanıtlamayı başarana kadar). Boyut bu nispeten basit durumda buluşsal yöntemlerden kaçınmaya izin verir.
AturSams

Ilmari, çok teşekkür ederim. Bu cevabın da anlaşılması gereken birkaç şey var. Rasgele şekiller biti, gelecekteki yinelemelerde yararlı olabilir.
Assembler
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.