Bir matristen en uygun yol


19

Pozitif tamsayılardan oluşan bir matris verildiğinde, sol üst elemandan sağ alt kısma doğru giderken yolu en düşük toplamla çıkar. Dikey, yatay ve çapraz olarak hareket edebilirsiniz. Hem yukarı / aşağı, sağa / sola hem de çapraz olarak tüm taraflara hareket etmenin mümkün olduğunu unutmayın.

Misal:

 1*   9    7    3   10    2    2
10    4*   1*   1*   1*   7    8
 3    6    3    8    9    5*   7
 8   10    2    5    2    1*   4
 5    1    1    3    6    7    9*

En düşük toplamı veren yol yıldızlarla işaretlenir ve aşağıdaki toplamla sonuçlanır: 1 + 4 + 1 + 1 + 1 + 5 + 1 + 9 = 23 .

Test senaryoları:

1   1   1
1   1   1
Output: 3

 7    9    6    6    4
 6    5    9    1    6
10    7   10    4    3
 4    2    2    3    7
 9    2    7    9    4
Output: 28

2  42   6   4   1
3  33   1   1   1
4  21   7  59   1
1   7   6  49   1
1   9   2  39   1
Output: 27 (2+3+4+7+7+1+1+1+1)

 5    6    7    4    4
12   12   25   25   25
 9    4   25    9    5
 7    4   25    1   12
 4    4    4    4    4
Output: 34 (5+12+4+4+4+1+4)

1   1   1   1
9   9   9   1
1   9   9   9
1   9   9   9
1   1   1   1
Output: 15

 2   55    5    3    1    1    4    1
 2   56    1   99   99   99   99    5
 3   57    5    2    2    2   99    1
 3   58    4    2    8    1   99    2
 4   65   66   67   68    3   99    3
 2    5    4    3    3    4   99    5
75   76   77   78   79   80   81    2
 5    4    5    1    1    3    3    2
Output: 67 (2+2+3+3+4+5+4+3+3+3+1+2+2+1+3+1+1+4+5+1+2+3+5+2+2)

Bu böylece her dilde en kısa kod kazanır.


Çok benzer , ancak çapraz harekete izin vermiyor.
Mego

7
@WheatWizard Katılmıyorum. Bu zorluğun diyagonal harekete izin verdiği çoğunlukla yüzeysel farklılıkların yanı sıra tüm pozisyonlara ulaşılabilir, diğer zorluk ise yolun maliyetinden ziyade yolun kendisinin geri dönmesini gerektirir. Her ikisini de döndüren yerleşik bileşenleri kullanmadığınız sürece kod değiştirilemez.
beher

@beaker Farkı gerçekten görmüyorum. Uzunluğunu bilmek için yolu bulmalısın. Buradaki fark, benim düşünceme göre çıktıdaki oldukça küçük bir fark ve bu meydan okuma, zaten bu meydan okuma tarafından kapsanmayan yeni veya ilginç bir şey sunmuyor.
Buğday Büyücüsü

1
@WheatWizard Buradaki çözümüm yolu bulamıyor. Bu olabilir yolunu bulmak değil, ayrı bir önceki dizisi ve mantık olmadan bir düğüm kendi öncelleri yapmaktan kaçınmaya. Sonunda yolu kurtarma bahsetmiyorum bile.
beher

@beaker Bence değişiklik oldukça önemsiz. Her ne kadar dupes sorusu, bir meydan okumadaki her bir geçerli girişin minimum çaba ile taşınıp taşınamayacağı değil , genel durum hakkındadır. Sadece buradaki çabaların çoğunun taşınabileceğini değil, bu zorluğun diğerinden yeni veya ilginç bir şey sunduğunu düşünmüyorum.
Buğday Büyücüsü

Yanıtlar:


8

JavaScript, 442412408358 bayt

Bu benim ilk PPCG başvurum. Geri bildirim takdir edilecektir.

(m,h=m.length,w=m[0].length)=>{for(i=0;i<h*w;i++)for(x=0;x<w;x++){for(y=0;y<h;y++){if(m[y][x]%1==0)m[y][x]={c:m[y][x],t:m[y][x]};for(X=-1;X<=1;X++)for(Y=-1;Y<=1;Y++){t=x+X;v=y+Y;if((X==0&&Y==0)||t<0||t>=w||v<0||v>=h)continue;if(m[v][t]%1==0)m[v][t]={c:m[v][t],t:null};c=m[y][x].t+m[v][t].c;if (c<m[v][t].t||m[v][t].t==null)m[v][t].t=c}}}return m[h-1][w-1].t}

Bu, giriş olarak çok boyutlu bir dizi alır.

açıklama

Temel olarak, komşuların her birine ulaşmak için bilinen en düşük maliyeti ayarlayarak tüm hücreler üzerinde tekrar tekrar döngü yapın. Sonunda, ızgara sağ alt tarafa ulaşmak için toplam maliyetin oraya ulaşmak için en düşük maliyet olduğu bir duruma ulaşacaktır.

gösteri

f=(m,h=m.length,w=m[0].length)=>{for(i=0;i<h*w;i++)for(x=0;x<w;x++){for(y=0;y<h;y++){if(m[y][x]%1==0)m[y][x]={c:m[y][x],t:m[y][x]};for(X=-1;X<=1;X++)for(Y=-1;Y<=1;Y++){t=x+X;v=y+Y;if((X==0&&Y==0)||t<0||t>=w||v<0||v>=h)continue;if(m[v][t]%1==0)m[v][t]={c:m[v][t],t:null};c=m[y][x].t+m[v][t].c;if (c<m[v][t].t||m[v][t].t==null)m[v][t].t=c}}}return m[h-1][w-1].t}

//Tests
console.log(f([[1,1,1],[1,1,1]])===3);
console.log(f([[7,9,6,6,4],[6,5,9,1,6],[10,7,10,4,3],[4,2,2,3,7],[9,2,7,9,4]])===28);
console.log(f([[2,42,6,4,1],[3,33,1,1,1],[4,21,7,59,1],[1,7,6,49,1],[1,9,2,39,1]])===27);
console.log(f([[5,6,7,4,4],[12,12,25,25,25],[9,4,25,9,5],[7,4,25,1,12],[4,4,4,4,4]])===34); 
console.log(f([[1,1,1,1],[9,9,9,1],[1,9,9,9],[1,9,9,9],[1,1,1,1]])===15)
console.log(f([[2,55,5,3,1,1,4,1],[2,56,1,99,99,99,99,5],[3,57,5,2,2,2,99,1],[3,58,4,2,8,1,99,2],[4,65,66,67,68,3,99,3],[2,5,4,3,3,4,99,5],[75,76,77,78,79,80,81,2],[5,4,5,1,1,3,3,2]])===67);

Düzenleme: Düzinelerce lezzetli bayt tıraş etmeme yardımcı olan @ETHproductions'a özel teşekkürler .

50 baytlık ipuçlarınızı @Stewie Griffin'e teşekkür ederiz .


3
PPCG'ye Hoşgeldiniz! Sonuna doğru kaldırabileceğiniz fazladan boşluklar var (toplamda 5 sayıyorum) ve }birkaç bayt tasarruf etmesi gereken noktalı virgüllerden herhangi birine doğrudan ihtiyacınız yok . Ayrıca değişkenlerinizi beyan etmeniz gerekmez; Sanırım vars kaldırmanız toplam 24 bayt daha tasarruf etmelidir.
Ağustos'ta ETHproductions

2
PPCG = 'ye hoş geldiniz) Zorluklarımdan birini başlangıç ​​noktası olarak seçmiş olmanıza sevindim. Benim tek yorumum: Açıklamaları çok seviyorum. Yine de isteğe bağlıdır, bu yüzden istemediğiniz sürece eklemeniz gerekmez. :)
Stewie Griffin

Bence m[v][t]bir değişken olarak depolamak : t=x+X;v=y+Y;k=m[v][t]daha kısa olacak ...?
Stewie Griffin

7

Python 3 + numpy + scipy , 239 222 186 bayt

from numpy import*
from scipy.sparse.csgraph import*
def f(M):m,n=s=M.shape;x,y=indices(s);return dijkstra([(M*(abs(i//n-x)<2)*(abs(i%n-y)<2)).flatten()for i in range(m*n)])[0,-1]+M[0,0]

Çevrimiçi deneyin!


6

Octave + Görüntü İşleme paketi, 175 162 157 151 142 139 bayt

@Luis Mendo sayesinde 14 bayt ve @notjagan sayesinde 1 bayt tasarruf edildi

function P(G)A=inf(z=size(G));A(1)=G(1);for k=G(:)'B=im2col(padarray(A,[1,1],inf),[3,3])+G(:)';B(5,:)-=G(:)';A=reshape(min(B),z);end,A(end)

Görüntü İşleme paketini kullanır, neden olmasın? Herkes grafik problemlerini böyle çözmez mi?

Çevrimiçi deneyin!

Ayrılmış

function P(G)
   A=inf(z=size(G));         % Initialize distance array to all Inf
   A(1)=G(1);                % Make A(1) = cost of start cell
   for k=G(:)'               % For a really long time...
      B=im2col(padarray(A,[1,1],inf),[3,3])+G(:)';
       %  B=padarray(A,[1,1],inf);     % Add border of Inf around distance array
       %  B=im2col(B,[3,3]);           % Turn each 3x3 neighborhood into a column
       %  B=B+G(:)';                   % Add the weights to each row
      B(5,:)-=G(:)';         % Subtract the weights from center of neighborhood
      A=reshape(min(B),z);   % Take minimum columnwise and reshape to original
   end
   A(end)                    % Display cost of getting to last cell

açıklama

Bir dizi ağırlık verildiğinde:

7   12    6    2    4
5   13    3   11    1
4    7    2    9    3
4    2   12   13    4
9    2    7    9    4

Bir maliyet dizisini, maliyeti ağırlığına eşit olan başlangıç ​​noktası (sol üst öğe) dışında, her bir öğeye ulaşmanın maliyeti Infinity olacak şekilde başlatın.

  7   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf

Bu yineleme 0'dır. Daha sonraki her yineleme için, bir hücreye ulaşma maliyeti minimum seviyeye ayarlanır:

  • o öğeye ulaşmak için geçerli maliyet ve
  • elemanın komşularına ulaşmak için geçerli maliyet + elemanın ağırlığı

İlk yinelemeden sonra, (2,2) öğesine giden yolun maliyeti (1 tabanlı indeksleme kullanarak)

minimum([  7   Inf   Inf]   [13  13  13]) = 20
        [Inf   Inf   Inf] + [13   0  13]
        [Inf   Inf   Inf]   [13  13  13]

İlk yinelemeden sonraki tam maliyet dizisi:

  7    19   Inf   Inf   Inf
 12    20   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf

Yinelemeden sonra k, her öğe en çok kadım atarak o öğeye ulaşmanın en düşük maliyeti olacaktır . Örneğin, (3,3) 'deki öğeye 22 adımda 2 adımda (yineleme) ulaşılabilir:

  7    19    25   Inf   Inf
 12    20    22   Inf   Inf
 16    19    22   Inf   Inf
Inf   Inf   Inf   Inf   Inf
Inf   Inf   Inf   Inf   Inf

Ancak 4. yinelemede, 20 basamaklı 4 adımlık bir yol bulunur:

 7   19   25   24   28
12   20   22   32   25
16   19   20   30   34
20   18   30   34   35
27   20   25   40   39

Mxn matrisi boyunca hiçbir yol , matristeki eleman sayısından daha uzun olamaz (çok gevşek bir üst sınır olarak), m*nyinelemelerden sonra her eleman, o öğeye başlangıçtan ulaşmak için en kısa yolun maliyetini içerecektir.


-1 bayt whileve arasındaki boşluğu kaldırarak ~.
notjagan

@notjagan ben den açık whileiçin forve hala ucu kullanmayı başardı. Teşekkürler!
beher

5

JavaScript, 197 bayt

a=>(v=a.map(x=>x.map(_=>1/0)),v[0][0]=a[0][0],q=[...(a+'')].map(_=>v=v.map((l,y)=>l.map((c,x)=>Math.min(c,...[...'012345678'].map(c=>a[y][x]+((v[y+(c/3|0)-1]||[])[x+c%3-1]||1/0)))))),v.pop().pop())

Güzelleştirmek:

a=>(
  // v is a matrix holds minimal distance to the left top
  v=a.map(x=>x.map(_=>1/0)),
  v[0][0]=a[0][0],
  q=[
     // iterate more than width * height times to ensure the answer is correct
    ...(a+'')
  ].map(_=>
    v=v.map((l,y)=>
      l.map((c,x)=>
        // update each cell
        Math.min(c,...[...'012345678'].map(
          c=>a[y][x]+((v[y+(c/3|0)-1]||[])[x+c%3-1]||1/0)
        ))
      )
    )
  ),
  // get result at right bottom
  v.pop().pop()
)

4

Mathematica 279 Bayt

Temel fikir, köşe matris girdileri karşılık gelen ve her iki köşe arasındaki yönelik kenarlar ile ayrılmış olan bir grafik oluşturmak için ChessboardDistancesıfırdan daha büyük, fakat daha az veya 1 tesadüfen e eşit, bu olarak bilinen olur Kral grafik bu karşılık geldiğinden bir kralın satranç tahtasındaki geçerli hareketleri.

FindShortestPathdaha sonra minimum yolu elde etmek için kullanılır. Çalışır EdgeWeight, değil VertexWeight, bu yüzden EdgeWeightyönlendirilen her kenarın hedefine karşılık gelen matris girişi olarak tanımlamak için bazı ekstra kodlar vardır .

Kod:

(m=Flatten[#];d=Dimensions@#;s=Range[Times@@d];e=Select[Tuples[s,2],0<ChessboardDistance@@(#/.Thread[s->({Ceiling[#/d[[1]]],Mod[#,d[[1]],1]}&/@s)])≤1&];Tr[FindShortestPath[Graph[s,#[[1]]->#[[2]]&/@e,EdgeWeight->(Last@#&/@Map[Extract[m,#]&,e,{2}])],1,Last@s]/.Thread[s->m]])&

Not karakter devrik sembolüdür. Mathematica'ya olduğu gibi yapışacaktır.

Kullanımı:

%@{{2, 55, 5, 3, 1, 1, 4, 1},
  {2, 56, 1, 99, 99, 99, 99, 5},
  {3, 57, 5, 2, 2, 2, 99, 1},
  {3, 58, 4, 2, 8, 1, 99, 2},
  {4, 65, 66, 67, 68, 3, 99, 3},
  {2, 5, 4, 3, 3, 4, 99, 5},
  {75, 76, 77, 78, 79, 80, 81, 2},
  {5, 4, 5, 1, 1, 3, 3, 2}}

Çıktı:

67

Ayarladıysanız g=Graph[...,GraphLayout->{"GridEmbedding","Dimension"->d},VertexLabels->Thread[s->m]ve p=FindShortestPath[...sonra aşağıdaki grafik çözümü görsel olarak görüntüler (matrisin üstü grafiğin altına karşılık gelir):

HighlightGraph[g,PathGraph[p,Thread[Most@p->Rest@p]]]

resim açıklamasını buraya girin


3

Haskell, 228 bayt

Pozisyonlar iki öğenin listesidir, çünkü bunlar sequence2-tuple ile eşleşmesi kolay ve desen eşlemesi kadar kolaydır.

h=g[[-1,-1]]
g t@(p:r)c|p==m=0|1<2=minimum$(sum$concat c):(\q@[a,b]->c!!a!!b+g(q:t)c)#(f(e$s$(\x->[0..x])#m)$f(not.e t)$zipWith(+)p#s[[-1..1],[-1..1]])where m=[l(c)-1,l(head c)-1]
(#)=map
f=filter
e=flip elem
s=sequence
l=length

Başlayın -1,-1ve her bir adım hedef alanının maliyetini sayın.

Alternatif ilk iki satır: başlangıç 0,0noktası, kalkış alanlarını sayın, matris boyutlarına eşit koordinatlarda sonlandırın (böylece hedeflerden sağa doğru, yasal hedefler listesine eklenmesi gerekir) - tam olarak aynı uzunlukta ancak daha yavaş:

j=i[[0,0]]
i t@(p@[a,b]:r)c|p==m=0|1<2=c!!a!!b+(minimum$(sum$concat c):(\q->i(q:t)c)#(f(e$m:(s$(\x->[0..x-1])#m))$f(not.e t)$zipWith(+)p#s[[-1..1],[-1..1]]))where m=[l c,l$head c]

İçin bir infix kullanmak mapburada bayt tasarrufu yapmaz, ancak bir maliyeti olmadığı anda değiştiririm, çünkü sadece daha fazla kullanımla ve bazen başka bir parantez tıraş eden diğer yeniden yapılandırmalarla daha iyi olabilir.

Geliştirilecekler: Gereksiz filters. İn-astar onları / birleştirme filter(flip elem$(s$(\x->[0..x])#m)\\p)ile import Data.Listiçin \\3 maliyetler bayt.

Ayrıca, çok kötü (fromEnumTo 0)2 bayt daha uzun (\x->[0..x]).

sum$concat ctüm alanların maliyeti özetlenir ve böylece minimumboş bir listeden kaçınmak için verilen yol maliyetine kısaca ifade edilebilir bir üst sınır (benim tip denetleyicim zaten üzerinde çalışacak her şeyi belirlemiştir Integer, bu nedenle maksimum kodlama , hehe). Adımları (algoritmayı çok hızlandıracak, fakat aynı zamanda maliyet bayt yapacak) bir öncekine göre nasıl kısıtlasam da, bu geri dönüşü gerekli kılan uçlardan kaçınamıyorum.

  • Bir filtre fikri, ilk yola eklenmeyi gerektiren ((not.e n).zipWith(-)(head r))çıkarma ile ilgilidir . Algoritma daha sonra önceki adımda daha önce gitmiş olabileceği yere gitmekten kaçınır, bu da kenar alanına ortogonal olarak o kenara çıkmaz bir çıkıntı yapar.n=s[[-1..1],[-1..1]],[-1,-1]

  • Bir diğeri, özyineleme ve ilk durumda verilen özyinelemeli işleve yeni bir argüman getiren ((>=0).sum.z(*)d)ayıklama ile oldu . Algoritma, negatif bir skaler ürünle ( önceki adım olmak üzere) art arda gelen adımları önler , bu da keskin 45 ° dönüşler anlamına gelir. Bu hala seçimleri önemli ölçüde daraltıyor ve önceki önemsiz çıkmazdan kaçınıyor, ancak yine de daha önce ziyaret edilen alanlarda (ve muhtemelen keskin bir dönüş olacak bir 'kaçış') kapsanan yollar var.z=zipWithd(z(-)p q)[1,1]d


3

Python 2, 356 320 bayt

s=input()
r=lambda x:[x-1,x,x+1][-x-2:]
w=lambda z:[z+[(x,y)]for x in r(z[-1][0])for y in r(z[-1][1])if x<len(s)>0==((x,y)in z)<len(s[0])>y]
l=len(s)-1,len(s[0])-1
f=lambda x:all(l in y for y in x)and x or f([a for b in[l in z and[z]or w(z)for z in x]for a in b])
print min(sum(s[a][b]for(a,b)in x)for x in f([[(0,0)]]))

Burada deneyin!

Notjagan sayesinde -36 bayt !

Bir liste listesini girdi olarak alır ve matriste sol üstten sağ alta doğru giderken en düşük maliyeti verir.

açıklama

Her bir rota için x, y koordinatları listesi oluşturarak, matrisin sol üstünden sağ alt kısmına mümkün olan her rotayı bulun. Güzergahlar geri izlenemez ve bitmesi gerekir (len(s)-1,len(s[0])-1).

Her koordinat yolu üzerindeki tam sayıları toplayın ve minimum maliyeti döndürün.

En printkısa rota için koordinat listesinin çıktısını almak üzere kolayca değiştirilebilir.


Çeşitli değişikliklerle -36 bayt .
notjagan

@notjagan Büyük değişiklikler, özellikle orde koşulların kullanımı. Teşekkür ederim!
Kurtuluş

1

APL (Dyalog Klasik) , 33 bayt

{⊃⌽,(⊢⌊⍵+(⍉3⌊/⊣/,⊢,⊢/)⍣2)⍣≡+\+⍀⍵}

Çevrimiçi deneyin!

{ } argüman ile işlev

+\+⍀⍵ yol mesafelerinde karamsar bir üst sınır oluşturmak için satır ve sütun ile kısmi toplamlar alabilir

( )⍣≡ yakınsamaya kadar tekrarlayın:

  • (⍉3⌊/⊣/,⊢,⊢/)⍣2komşularına mesafeleri dak, yani iki kez (do ( )⍣2): başa getirebilir soldaki sütun ( ⊣/,öz (kadar) ) ve ekleme sağdaki sütunlar ( ,⊢/), (yatay üçüzlerde minimum noktalarının 3⌊/() ve devrik )

  • ⍵+ her bir düğümün değerini komşularına olan mesafelerin minimumuna ekleyin

  • ⊢⌊ mevcut en iyi mesafeleri geçmeye çalışın

⊃⌽, Son olarak, sağ alt hücreyi döndür

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.