桥梁和火炬问题


17

高尔夫难题代码的灵感来自桥梁和火炬问题,其中d的人们必须在最短的时间内跨过桥梁的起点。

要注意的是,最多两个人可以一次过桥,否则桥将因他们的重量而压碎,这群人只有一根火炬可以通过桥。

整个拼图中的每个人都有指定的时间走过桥。如果两个人交叉在一起,那对人和最慢的人一样慢。

没有一定数量的人必须过桥。您的解决方案必须适用于d的任何值。

您无需为此问题使用标准输入,但是为了解释该问题,我将使用以下输入和输出格式进行解释。第一个数字d是桥梁开始处的人数。然后,代码将扫描d个数字,每个数字代表一个人的速度。

代码输出将是从桥的起点到桥的终点穿越每个人,同时满足前面说明的标准所需的最少时间。

以下是一些输入案例和输出案例以及第一个输入案例的说明。您可以根据这些信息派生算法,以尽可能少的代码字节来解决问题。

输入

4
1 2 5 8

输出

15

为了达到这一目标,人民必须以下列方式进行交往。

A and B cross forward (2 minutes)
A returns (1 minute)
C and D cross forward (8 minutes)
B returns (2 minutes)
A and B cross forward (2 minutes)

这是另一个测试用例,可以指导您逐步进行。

输入

5
3 1 6 8 12

输出

29

规则:

  1. 假设不会对输入进行排序,并且您必须自己进行排序(如果需要)
  2. 拼图中的人数不固定为4(N> = 1)
  3. 每个团体和个人穿越都必须有火炬。火炬只有一个。
  4. 每个小组最多只能由2个人组成!
  5. 不,您可能不会跳下桥去游泳到另一边。没有其他这样的把戏;)。

正如下面xnor所发现的,请务必测试像这样的用例1 3 4 5,该用例应该返回14而不是
15。–很高兴

1 4 5 6 7有类似的问题。25比26
Sherlock9年

1
这似乎是一个奇怪的问题,但是难题中的最小和最大人数是多少?在制定解决方案时,我注意到他们只处理N >= 2人员(这很奇怪,这是处理“ 1个人需要越过”这一琐碎情况的额外工作),因此对此点进行一些澄清将是非常好的。提前致谢。
Sherlock16年

@ Sherlock9假设您的解决方案必须适用于N> = 1
baseman101 '16

测试案例表明,我们可以将长度用作参数,但是您可以在规则中更清楚地说明这一点吗?输入是被允许为时间和人数的数组,还是仅是时间?
Sherlock16年

Answers:


8

Python 3中,100个 99字节

递归解决方案

f=lambda s:s[0]+s[-1]+min(2*s[1],s[0]+s[-2])+f(s[:-2])if s.sort()or 3<len(s)else sum(s[len(s)==2:])

感谢@xnor撰写本文

感谢@lirtosiast保存2个字节,@movatica保存1个字节,并@gladed指出我以前的解决方案不起作用

使用以下技巧在lambda函数中求值,在s.sort() or s 这里我们计算排序并返回测试结果s.sort()or len(s)>3

不打高尔夫球

def f(s):
    s.sort()                                   # sort input in place
    if len(s)>3:                               # loop until len(s) < 3
        a = s[0]+s[-1]+min(2*s[1],s[0]+s[-2])  # minimum time according to xnor paper
        return  a + f(s[:-2])                  # recursion on remaining people
    else:
        return sum(s[len(s)==2:])              # add last times when len(s) < 3

结果

>>> f([3, 1, 6, 8, 12])
29
>>> f([1, 2, 5, 8])
15
>>> f([5])
5
>>> f([1])
1
>>> f([1, 3, 4, 5])
14

您可以保存1个字节并更改len(s)==2len(s)<3
Mr Public

@MrPublic您发现错误,我改变了它的解决方案s[0]*(len(s)==2)不是(s[0]*len(s)==2) 用BUG f([1]) -> 0就是为什么我们不能代替<3的感谢
二万

本文的最佳时间表达是多种可能性中的最小值。您确定您的解决方案在所有情况下都是最优的吗?
xnor

@xnor哇,看来我有最佳解决方案,我使用引理3中的表达式A5:22
Erwan

1
与您的建议@movatica更新
二湾

4

Python 2中,119个 114 112 119 110 100 95字节

建议我将答案分开。

一种使用Theorem 1, A2:09 本文xnor链接的解决方案。引用纸张(将其更改为零索引):The difference between C_{k-1} and C_k is 2*t_1 - t_0 - t_{N-2k}.

lambda n,t:t.sort()or(n-3)*t[0]*(n>1)+sum(t)+sum(min(0,2*t[1]-t[0]-t[~k*2])for k in range(n/2))

开球:

def b(n, t): # using length as an argument
    t.sort()
    z = sum(t) + (n-3) * t[0] * (n>1) # just sum(t) == t[0] if len(t) == 1
    for k in range(n/2):
        z += min(0, 2*t[1] - t[0] - t[-(k+1)*2]) # ~k == -(k+1)
    return z

您确定我们可以假设长度可以作为参数吗?
Erwan

@Erwan示例测试用例似乎允许它。我问
Sherlock9年

2

Ruby,94 133 97 96 101 96 99字节

建议我将答案分开。

这是基于在所描述的算法中的溶液A6:06-10本文所述桥和火炬问题

编辑:修复了在if结束a=s[0]时尚未定义何时a调用的错误s.size <= 3

->s{r=0;(a,b,*c,d,e=s;r+=a+e+[b*2,a+d].min;*s,y,z=s)while s.sort![3];r+s.reduce(:+)-~s.size%2*s[0]}

开球:

def g(s)
  r = 0
  while s.sort![3]      # while s.size > 3
    a, b, *c, d, e = s  # lots of array unpacking here
    r += a + e + [b*2, a+d].min
    *s, y, z = s        # same as s=s[:-2] in Python, but using array unpacking
  end
  # returns the correct result if s.size is in [1,2,3]
  return r + s.reduce(:+) - (s.size+1)%2 * s[0]
end

1

Scala 113 135(达尼特色)

def f(a:Seq[Int]):Int={val(s,b)=a.size->a.sorted;if(s<4)a.sum-(s+1)%2*b(0)else b(0)+Math.min(2*b(1),b(0)+b(s-2))+b(s-1)+f(b.take(s-2))}

松散一些:

def f(a:Seq[Int]):Int = {
    val(s,b)=a.size->a.sorted      // Sort and size
    if (s<4) a.sum-(s+1)%2*b(0)    // Send the rest for cases 1-3
    else Math.min(b(0)+2*b(1)+b(s-1),2*b(0)+b(s-2)+b(s-1)) + // Yeah.
        f(b.take(s-2))             // Repeat w/o 2 worst
}

测试人员:

val tests = Seq(Seq(9)->9, Seq(1,2,5,8)->15, Seq(1,3,4,5)->14, Seq(3,1,6,8,12)->29, Seq(1,5,1,1)->9, Seq(1,2,3,4,5,6)->22, Seq(1,2,3)->6, Seq(1,2,3,4,5,6,7)->28)
println("Failures: " + tests.filterNot(t=>f(t._1)==t._2).map(t=>t._1.toString + " returns " + f(t._1) + " not " + t._2).mkString(", "))

总体来说并不算好,但对于强类型的语言来说可能还不错。还要感谢xnor发现了我没发现的案件。


本文的最佳时间表达是多种可能性中的最小值。您确定您的解决方案在所有情况下都是最优的吗?
xnor

1

Ruby,104 95 93字节

建议我将答案分开。

这是基于解决我的Python 2溶液Theorem 1, A2:09文章上桥和火炬问题

->n,t{z=t.sort!.reduce(:+)+t[0]*(n>1?n-3:0);(n/2).times{|k|z+=[0,2*t[1]-t[0]-t[~k*2]].min};z}

开球:

def b(n, t) # using length as an argument
  z = t.sort!.reduce(:+) + t[0] * (n>1 ? n-3 : 0)
  (n/2).times do each |k|
    a = t[1]*2 - t[0] - t[-(k+1)*2] # ~k == -(k+1)
    z += [0, a].min
  end
  return z
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.