鉄道線路を構築し、政府をごまかす


30

あなたは、19世紀のアメリカの鉄道起業家です。列車は、大量の資材を陸路で輸送する最も効率的な手段であるため、人気が高まっています。東海岸から西の最近植民地化された土地を通る鉄道線路に対する国家的なニーズがあります。

このニーズに対応するために、米国政府は鉄道を助成するために税金を徴収する予定です。彼らは敷設された線路のマイルごとにあなたの鉄道会社にお金を払うことを約束しました。丘陵地や山岳地帯にトラックを敷設することは、平らな土地にトラックを敷設するよりも高価なので、彼らはそれに応じて与える量を調整します。つまり、政府は支払います

  • 平らな土地に敷設されたトラック1マイルあたり5,000ドル
  • 丘陵地に敷設された1マイルあたり12,500ドル
  • 山に敷設された1マイルあたり2万ドル。

もちろん、この計画は、トラックを敷設するのに実際にかかる費用を正確に反映していません。

いくつかの地図製作者を雇って、標高を分析するためのトラックを敷設する地域のレリーフマップを描画しました。そのようなマップの1つを次に示します。

S12321
121234
348E96

各数字は1平方マイルの土地を表します。Sは開始点、E終了点です。各数値は、その地域の標高変化の強度を表します。

  • 1〜3番の土地は平坦な土地を構成します。
  • 4〜6番の土地は丘陵地を構成しています。
  • 7-9番の土地は山脈を構成します。

長年の鉄道線路の構築経験を通じて、線路構築のコスト(ドル単位)は次の式を満たしていると評価されました。

Cost_Per_Mile = 5000 + (1500 * (Elevation_Rating - 1))

つまり、特定の標高勾配に基づいて構築すると、政府が提供するよりも多くのお金が必要になります。場合によっては利益があり、場合によっては損益分岐点になります。

たとえば、標高勾配が3の1マイルのトラックの建設費用は8,000ドルですが、支払われるのは5,000ドルだけなので、3000ドルを失います。対照的に、標高勾配7で1マイルのトラックを構築すると14,000ドルの費用がかかりますが、そのために20,000ドルが支払われ、6,000ドルの利益が得られます。

次に、マップの例と2つの異なる可能なパスを示します。

S29    S#9    S##
134    1#4    1##
28E    2#E    2#E

最初のトラックの建設には30,000ドルかかりますが、政府はそれに対して30,000ドルを支払います。このトラックから利益を得ることはありません。

一方、2つ目のビルドには56,500ドルかかりますが、62,500ドルが支払われます。このトラックから6,000ドルの利益を得ます。

あなたの目標:レリーフマップが与えられたら、最初から最後まで最も収益性の高い(または単に最も安価な)パスを見つけます。複数のパスが結び付けられている場合、それらのいずれかが許容可能なソリューションです。

プログラムの詳細

数値の長方形マップと1つの開始点と終了点で区切られたテキスト入力が与えられます。各数値は1から9までの整数になります。それ以外の理由で、必要に応じて入力を提供できます。

出力は入力と同じ形式である必要があり、トラックが構築された番号はハッシュ(#)に置き換えられます。気まぐれな政治家によって課せられたarbitrary意的な規制のため、トラックは水平方向または垂直方向にしか移動できません。つまり、バックトラックしたり、斜めに行くことはできません。

プログラムは、最大6行6列のマップの妥当な時間(10分未満)で解決できる必要があります。

これはコードゴルフチャレンジなので、最短のプログラムが勝ちます。

(ゴルフではない)実装例があります

サンプルI / O

S12321
121234
348E96

S12321
######
3##E##



S73891
121234
348453
231654
97856E

S#3###
1###3#
3#####
######
#####E

出力があいまいな場合はどうなりますか?
FUZxxl

2
出力はあいまいになる場合がありますが、トレース方法に関係なく利益が同じになるようにあいまいになります。
ピーターオルソン

小さな間違いがあると思います。なければならない4134例のマップであること6
JiminP

@JiminPはい、それはある場所で数字を変更することによる誤りであり、別の場所ではそうではありませんでした。今すぐ修正する必要があります。
ピーターオルソン

3
3年後、政府は周りを見回して、なぜすべての丘と山が鉄道線路で覆われているのかと考え始めます。しかし、地元の交通機関のユーザーは、政府が資金を提供し、人々をより幸せにしてくれる素敵なジェットコースター/ツアーに乗ってくれました。(*一部グレード-6の丘を除く)
ジョン・ドヴォルザーク

回答:


5

Python、307文字

import os
I=os.read(0,99)
n=I.find('\n')+1
I='\0'*n+I+'\0'*n
def P(p):
 S=[]
 for d in(-n,-1,1,n):
  y=p[-1]+d
  if'E'==I[y]:S+=[(sum((int(I[v])-1)/3*75-15*int(I[v])+15for v in p[1:]),p)]
  if'0'<I[y]<':'and y not in p:S+=P(p+[y])
 return S
for i in max(P([I.find('S')]))[1][1:]:I=I[:i]+'#'+I[i+1:]
print I,

Pは部分的な経路pを取り、それを到達するまで延長するすべての方法を返しますE。返された各パスはそのスコアとペアになっているmaxため、最適なパスを見つけることができます。

6x6マップでは約80秒かかります。


1
あなたは3つの文字を保存するには、タブとインデントの第二のレベルを置き換えることができます
gnibbler

4

Python:529 482 460バイト

私のソリューションは賞品を獲得しません。ただし、投稿されたソリューションは2つしかなく、問題が興味深いことがわかったので、とにかく答えを投稿することにしました。

編集:ハワードの勧告に感謝します。スコアをかなり削ることができました!

import sys
N=len
def S(m,c,p=0):
 if m[c]=='E':return m,p
 if m[c]<'S':
    b=list(m);b[c]='#';m=''.join(b)
 b=[],-float('inf')
 for z in(1,-1,w,-w):
    n=c+z
    if 0<=n<N(m)and m[n]not in('S','#')and(-2<z<2)^(n/w!=c/w):
     r=S(m,n,p+(0if m[n]=='E'else(int(m[n])-1)/3*5-int(m[n])+1))
     if b[1]<r[1]:b=r
 return b
m=''
while 1:
 l=sys.stdin.readline().strip()
 if l=='':break
 w=N(l);m+=l
b,_=S(m,m.index('S'))
for i in range(0,N(b),w):print b[i:i+w]

それが始まりです。:)
ジョナサンヴァンマトレ14年

1
いくつかのマイナーな改善:Pそして、Mそれぞれ一度だけ使用されるので、インライン化することをお勧めします(1回の呼び出しでは、ほとんどすべての場合に2回動作します)。m[c]!='S'短縮することができm[c]<'S'、また、abs(z)==1abs(z)<2たり-2<z<2
ハワード14年

「マイナーな改善」により、47バイト節約できます。回答を編集しています。
貞勝14年

3

ルビー、233文字

R=->s{o=s=~/S/m
s=~/E/m?(q=[-1,1,-N,N].map{|t|s[f=o+t]>'0'?(n=s*1
n[o]='#'
n[f]='S'
a=R[n]
a&&[a[0]-(e=s[f].to_i-1)/3*5+e,a[1]]):nil}-[nil]
q.sort!&&q[0]):[0,(n=s*1;n[o]='E'
n[$_=~/S/m]='S'
n)]}
N=1+(gets(nil)=~/$/)
$><<R[$_+$/*N][1]

6x6ボードの時間制約内で適切に実行されるRubyの総当たり攻撃アプローチ。入力はSTDINで指定する必要があります。

例:

S12321
121234
348E96

S#2321
1#####
3##E##    
--    
S73891
121234
348453
231654
97856E

S#####
1212##
#####3
#3####
#####E

@PeterOlsonあなたの挑戦に少なくとも少し注意を向けようとしました;-)
ハワード14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.