ピーク体験:すべてのピークをすばやく訪問


22

私は、たとえば、高度が数字で表されるx マップのポイント(0,0)に立っています。HW

1132
2221
1230    # H = 3, W = 4

すべてのピークからの景色を体験したいと思います3。この場合は、標高の高いエリアです。しかし、丘を登るのは簡単なことではなく、私も時間を使い果たしています。

チャレンジ

課題は、すべてのピークを訪れて戻ってくるための最速のパスを見つけることです。

最短のプログラムが勝ちます。

入力

  • H、W-マップの高さと幅(整数)(オプション、リスト/タプルまたは2つの個別の整数入力)
  • 任意の便利な形式(2Dリスト、改行で区切られた文字列など)HW数字のセット(0- 9)として与えられるマップ

出力

  • すべてのピークを訪れて出発点に戻るまでの最短時間(整数)

条件

  • 特定のエリアの高度は、0〜の数字で表され9ます。
  • 「ピーク」は、最高高度のエリアによって定義されます。
  • パスは、左上(0,0)領域で開始および終了する必要があります。
  • 現在のエリアに隣接するエリアにのみ移動でき、斜めに移動することはできません。
    • 高度に変化がない場合、あるエリアから別のエリアに移動するのに3分かかります。
    • 登るには11分かかります。つまり、あるエリアから別のエリアに移動し1ます。これは正確に単位が高くなります。
    • 降りるのに2分かかります。つまり、あるエリアから別のエリアに移動し1ます。これは正確に単位が低くなります。
    • 現在地よりも1 1ユニット以上高いまたは低いエリアに移動することはできません。(高度のあるエリアから1隣接する高度のあるエリアに移動することはできません。たとえば、3
  • すべてのピークへのパスが保証されています
  • ピークの最大数はです15

サンプル

入力

4 5
32445
33434
21153
12343

出力

96

説明

左上から始め3ます。次の2つの訪問しなければならない5に位置しているのを(0,4)(3,3)し、戻ってくる3(0,0)最短時間で。

3  2  4->4->5
V     ^
3->3->4  3  4

2  1  1  5  3

1  2  3  4  3    # 3 + 3 + 11 + 3 + 3 + 11 = 34 minutes to visit 1st peak


3  2  4  4  5
            V
3  3  4  3  4
            V
2  1  1  5  3
         ^  V
1  2  3  4<-3    # 2 + 2 + 3 + 11 + 11 = 29 minutes to visit 2nd


3  2  4  4  5
^            
3  3  4  3  4
^            
2  1  1  5  3
^        V   
1<-2<-3<-4  3    # 2 + 2 + 2 + 2 + 11 + 11 + 3 = 33 minutes to come back

# 34 + 29 + 33 = 96 minutes total is the answer

入力

2 7
6787778
5777679

出力

75

9
PPCGへようこそ。最初の質問です。回答を採点するには客観的な勝利基準が必要なので、これをコードゴルフの質問に変更することを強くお勧めします。
デウソビ

4
推奨していただきありがとうございます、私はヘルプセンターのルールを読んで質問を編集しました
-cozyconemotel

タイトルが改善された場合、おそらくあなたの挑戦はより多くのヒットを受け取るでしょう。「山登りチャレンジ」。
DavidC

1
cozyconemotel、私はあなたの挑戦のために、より短く、おそらくより魅力的なタイトルを提案しました。ご希望の場合は、元の名前に戻してください。(
送信し

@DavidC私は完全に同意します。編集していただきありがとうございます。
cozyconemotel

回答:


5

Mathematica 745 681バイト

基本的な考え方は、可能な動きの重み付きグラフを作成することです。重みは、ある場所から次の場所に移動するのにかかる時間です。重みが最小のパスが最も速くなります。

入力数字は、r x c(行x列)の長方形配列に配置され、3つの異なる表現が作用します:(1)r x cグリッドグラフ、各頂点は配列内のセルに対応、(2) (r c)by(r c)ある場所(グリッドグラフ)から別の場所に移動するのにかかる時間(2、3、または11分)に対応する重みを保持する重み付き隣接行列、および(3)有向、マトリックスから作成された重み付き隣接グラフ。

グリッドグラフは、各セルからどのセル(つまり頂点)に到達できるかを判断するのに役立ちます。隣接セルは特定のセルの右、左、上、または下だけではないため、「到達可能」です。また、その値は、近隣から1単位の距離内にある必要があります(たとえば、3は近隣の5または1に接続しません)。頂点aが頂点に接続されていない場合b、隣接行列セル{a、b}および{b、a}の値は∞になります。したがって、重み付き隣接グラフには、aからbへのエッジもbからaへのエッジもありません。

重み付き隣接グラフはGraphDistance、頂点間の最短距離()および最短ルートを決定するのに役立ちます。最適なパスは1で始まり、各ピークに触れて、1に戻る必要があります。この場合、「最短ルート」は必ずしも移動が最も少ないルートではありません。これは、エッジの重みで測定された、全体の時間が最も短いものです。


ゴルフ

o=Sequence;v[a_<->b_,z_]:=(m_~u~q_:={Quotient[m-1,q[[2]]]+1,1+Mod[m-1, q[[2]]]};j=z[[o@@u[a,i=Dimensions@z]]];k=z[[o@@u[b,i]]];Which[j==k,{{a,b}->3,{b,a}->3},j==k-1,{{a,b}->11,{b,a}->2},j==k+1,{{a,b}->2,{b,a}->11},2<4,{{a,b}->∞, {b, a}->∞}]);w@e_:=Module[{d,x,l,y},x=Map[ToExpression,Characters/@Drop[StringSplit@e,2],{2}];d_~l~c_:=d[[2]](c[[1]]-1)+c[[2]];g_~y~p_:=(Min[Plus@@(GraphDistance[g,#,#2]&@@@#)&/@(Partition[#,2,1]&/@({1,o@@#,1}&/@Permutations@p))]);y[WeightedAdjacencyGraph[ReplacePart[ConstantArray[∞,{t=Times@@(d=Dimensions@x),t}],Flatten[#~v~x &/@Union@Flatten[EdgeList[GridGraph@Reverse@d,#<->_]&/@Range@(Times@@d),1],1]]], l[Dimensions@x, #] & /@ Position[x, Max@x]]

長くて読みやすい形式

(*determines a weight (number of minutes) to go from vertex a to b and from b to a*)
weight[a_ <-> b_, dat_]:= 
  Module[{cellA,cellB,dim,valA,valB,vertexToCell},

  (*Convert graph vertex index to cell location*)
  vertexToCell[m_,dimen_]:={Quotient[m-1,dim[[2]]]+1,1+Mod[m-1,dimen[[2]]]};
     dim=Dimensions[dat];
     cellA = vertexToCell[a,dim];
     cellB = vertexToCell[b,dim];
     valA=dat[[Sequence@@cellA]];
     valB=dat[[Sequence@@cellB]];
     Which[
       valA==valB,{{a,b}-> 3,{b,a}-> 3},
       valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
       valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
       2<4,{{a,b}->∞,{b,a}->∞}]];

(* weights[] determines the edge weights (times to get from one position to the next), makes a graph and infers the shortest distance 
from vertex 1 to each peak and back.  It tries out all permutations of peaks and 
selects the shortest one. Finally, it returns the length (in minutes) of the shortest trip. *)

weights[str_]:=
  Module[{d,dat,neighbors,cellToVertex,peaks,z,gd},
  dat=Map[ToExpression,Characters/@Drop[StringSplit[str],2],{2}];
  cellToVertex[dim_,cell_]:=dim[[2]] (cell[[1]]-1)+cell[[2]];
  peaks[dat_]:= cellToVertex[Dimensions[dat],#]&/@Position[dat,peak =Max[dat]];

     (* to which cells should each cell be compared? neighbors[] is a function defined within weights[]. It returns a graph, g, from which graph distances will be derived in the function gd[] *)
  neighbors[dim_]:=
  Union@Flatten[EdgeList[GridGraph[Reverse@dim],#<->_]&/@Range@(Times@@dim),1];
    d=Dimensions[dat];
    m=ReplacePart[ConstantArray[∞,{t=Times@@d,t}], 
     (*substitutions=*)
    Flatten[weight[#,dat]&/@neighbors[d],1]];
    g=WeightedAdjacencyGraph[m,VertexLabels->"Name",ImageSize->Full,GraphLayout->"SpringEmbedding"];

    (* finds shortest path.  gd[] is also defined within weights[] *)
  gd[g3_,ps_]:=
    Module[{lists,pairs},
    pairs=Partition[#,2,1]&/@({1,Sequence@@#,1}&/@Permutations@ps);
    Min[Plus@@(GraphDistance[g3,#,#2]&@@@#)&/@pairs]]; 

  gd[g,peaks[dat]]]

テスト

weights["4 5
 32445
 33434
 21153
 12343"]

96。


weights@"2 7
 6787778
 5777679"

75。


weights@"3 4
 1132
 2221
 1230"

51。


説明

次の入力の2〜5行目を考えてください

"4 5
 32445
 33434
 21153
 12343"

4行5列の配列を表すもの:

グリッドグラフ

ここで、各頂点は入力配列の数字に対応します。3は頂点1、2は頂点2、4は頂点3、もう4は頂点4、5は頂点5などです。グリッドグラフは大まかなものです目指しているグラフの近似。無向です。さらに、エッジの一部は使用できなくなります。(覚えておいてください:現在の位置から上下に1単位以上の位置から別の位置に移動することはできません。)しかし、グリッドグラフを使用すると、選択した頂点の隣にある頂点を簡単に見つけることができます。これにより、最初の例(4 x 5グリッド)で考慮する必要があるエッジの数が400(20 * 20)から62(31 * 2はグリッドグラフのエッジの数)に減少します。同じ例では、動作するエッジは48のみです。14はそうではありません。

次の20 x 20の重み付き隣接行列は、グリッドグラフからのすべての頂点のペア間の距離を表します。

割り当てる番号を決定するキーコードは次のとおりです。

Which[
      valA==valB,{{a,b}-> 3,{b,a}-> 3},
      valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
      valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
      2<4,{{a,b}->∞,{b,a}->∞}]

セル{1,2}-ワンインデクシング-には、頂点1から頂点2への移動が下り坂のため、値2が含まれています。セル{2,1}には11が含まれます。これは、頂点2から頂点1への移動が上り坂だからです。セル{1,6}および{6,1}の3は、動きが上でも下でもないことを示します。セル{1,1}はそれ自体に接続されていないため、∞を含んでいます。

重り

次のグラフは、上記の入力の基礎となる構造を示しています。色付きの矢印は、頂点1からピーク(5および14)に戻り、1に戻る最適なパスを示しています。青い矢印は、同じレベル(3分)の動きに対応しています。赤い矢印は上昇(11分)を意味し、緑の矢印は下降(2分)を示します。

graph2

頂点1(セル{1,1}から2つのピークまで、そして頂点1に戻るパス)

3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3

96


0

Pyth、92バイト

hSms@Lu.dm,bhS,@Gb+@G,hbH@G,HebG[FQ.dm,(Fb?|tsaMCb>.aJ-F@LQb1.n4@[3hT2)J*QQC.<B+]hSQd1.p.M@Q

入力形式は、座標を高さにマッピングする辞書です{(0, 0): 3, (0, 1): 2, (0, 2): 4, …}。これにより、Floyd–Warshallアルゴリズムを使用して、すべてのポイントペア間の最速パスが検索され、ピークのすべての順列で必要なサイクルの合計時間が最小化されます。

オンラインで試す

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.