Go语言“ n”个人的桥梁和火炬问题[关闭]

Problem: Given an array of positive distinct integer denoting the crossing time of ‘n’ people. These ‘n’ people are standing at one side of bridge. Bridge can hold at max two people at a time. When two people cross the bridge, they must move at the slower person’s pace. Find the minimum total time in which all persons can cross the bridge.

I am not able to find the pattern as of how to scale this for 'n' people. But somehow I managed to find the case with 4 people. Can someone help me with this. I am new to Golang and I am stuck with this problem.

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "sort"

    "gopkg.in/yaml.v2"
)

type conf struct {
    Person []map[string]float32 `yaml:"person"`
}

func (c *conf) getConf() *conf {
    filename := os.Args[1]                     // Taking file input
    yamlFile, err := ioutil.ReadFile(filename) // Yaml parse
    if err != nil {
        log.Printf("yamlFile.Get err   #%v ", err)
    }
    err = yaml.Unmarshal(yamlFile, c)
    if err != nil {
        log.Fatalf("Unmarshal: %v", err)
    }
    return c
}

func main() {
    var c conf  // Object of struct conf
    c.getConf() // calling getConf function
    // Sorting the current conf map
    n := map[float32][]string{} // Map to store current conf map
    var a []float32             // Store values from conf map
    for k, v := range c.Person {
        v := float32(v)
        fmt.Println(k, v)
        n[v] = append(n[v], k)
    }
    for k := range n {
        a = append(a, k)
    }
    // Converting float32 as float64 in order to sort the values in conf map
    float32AsFloat64Values := make([]float64, len(a))
    for i, val := range a {
        float32AsFloat64Values[i] = float64(val)
    }
    sort.Float64s(float32AsFloat64Values)
    for i, val := range float32AsFloat64Values {
        a[i] = float32(val)
    }
    var time float32
    fmt.Printf("
%v
", a)
    for _, k := range a {
        min1 := a[0]
        min2 := a[1]
        min3 := a[2]
        for _, s := range n[k] {
            //Debug:
            fmt.Printf("%s, %g
", s, k)
            if len(a) > 3 {
                time = (3 * min2) + min1 + a[3] //Formula for minimum time in case of 4 people
            } else if len(a) == 3 {
                time = min1 + min2 + min3
            } else {
                fmt.Println("Enter valid arguments in config.yaml")
            }
        }
    }
    fmt.Printf("Minimum time taken to cross the bridge is:\t%g
", time)
}

Playground: https://play.golang.org/p/ObTVA8gk0mg

Config.yaml is:

person:
  person_1: 2
  person_2: 1
  person_3: 5
  person_4: 8
  person_5: 9

One could run this as: 'go run main.go config.yaml'. My scenario is that there could be 4,5 or 'n' number of people given in this yaml. Then what would be the minimum time for them to cross the bridge given the constraints.

I think the original problem is a bit more interesting than the one stated (yes, there has to be a Torch in the "Bridge and Torch" problem!).

Based on the Wikipedia description, for example,

Four people come to a river in the night. There is a narrow bridge, but it can only hold two people at a time. They have one torch and, because it's night, the torch has to be used when crossing the bridge. Person A can cross the bridge in 1 minute, B in 2 minutes, C in 5 minutes, and D in 8 minutes. When two people cross the bridge together, they must move at the slower person's pace. The question is, can they all get across the bridge if the torch lasts only 15 minutes?

In our case, of course, there are N people instead of just four, and it takes them variable amount of time to cross the bridge, but the rest of the story is the same.

Here's the implementation:

import (
    "fmt"
    "sort"
)

func minCrossingTime(x []int) int {
    if len(x) == 1 {
        return x[0]
    }

    sort.Ints(x)

    t := 0
    a, b := x[0], x[1]
    x = x[2:]

    for len(x) >= 2 {
        n := len(x)
        c, d := x[n-2], x[n-1]
        x = x[:n-2]

        t1 := 2*b + a + d
        t2 := d + c + 2*a
        if t1 < t2 {
            t += t1
        } else {
            t += t2
        }
    }

    if len(x) == 1 {
        c := x[0]
        t += a + b + c
    } else {
        t += b
    }
    return t
}

func main() {
    x1 := []int{1, 2, 5, 8}
    fmt.Printf("x = %x, time = %d
", x1, minCrossingTime(x1))
    x2 := []int{3, 8, 1, 6, 2, 9}
    fmt.Printf("x = %x, time = %d
", x2, minCrossingTime(x2))
}

Output:

x = [1 2 5 8], time = 15
x = [1 2 3 6 8 9], time = 27

Note: the first example [1 2 5 8] is straight from the Wikipedia, so the answer is yes, they can cross in 15 minutes

Key idea:

Definitions:

  • Let X = [X1,X2,...,XN] be the sorted array of crossing times with X1 being the fastest and XN the slowest
  • Let's denote as {XI,XJ} crossing by the pair of people XI and XJ, and {XK} crossing by one person XK, with +{...} indicating the crossing in the desired direction and -{...} in the opposite direction

Logic:

  1. If N < 4 the problem is trivial:

    • N = 1 => t = X1 (+{X1})
    • N = 2 => t = X2 (+{X1,X2})
    • N = 3 => t = X1 + X2 + X3 (+{X1,X2} -{X1} + {X1,X3})
  2. If N >= 4 consider the following problem: how to make two slowest people (and only them) cross the bridge and have the torch brought back in minimal time. There are two "good" ways to do it, with times t1 = X1 + 2*X2 + XN (+{X1,X2} -{X1} +{X[N-1],XN} -{X2}) and t2 = 2*X1 + X[N-1] + XN (+{X1,X[N-1]} -{X1} +{X1,XN} -{X1}), so we choose the best (minimum) out of these two

  3. Now the two slowest have crossed the bridge, and the torch is on the same side where it started, so we are left with the original problem for X' = [X1, X2, ..., X[N-2]], which can be solved iteratively by applying the same logic and summing up the crossing times

Extras:

  1. For mathematical proof and more context see e.g. https://page.mi.fu-berlin.de/rote/Papers/pdf/Crossing+the+bridge+at+night.pdf
  2. Code golf solutions in different programming languages: https://codegolf.stackexchange.com/questions/75615/the-bridge-and-torch-problem

Problem: Given an array of positive distinct integer denoting the crossing time of ‘n’ people. These ‘n’ people are standing at one side of bridge. Bridge can hold at max two people at a time. When two people cross the bridge, they must move at the slower person’s pace. Find the minimum total time in which all persons can cross the bridge.

person:
  person_1: 2
  person_2: 1
  person_3: 5
  person_4: 8
  person_5: 9

Your algorithm looks complicated.

For example,

package main

import (
    "fmt"
    "sort"
)

func minCrossingTime(people []int) int {
    sort.Slice(people, func(i, j int) bool {
        return people[i] > people[j]
    })
    min := 0
    for i := 0; i < len(people); i += 2 {
        min += people[i]
    }
    return min
}

func main() {
    people := []int{2, 1, 5, 8, 9}
    fmt.Println(len(people), people)
    crossingTime := minCrossingTime(people)
    fmt.Println(len(people), people)
    fmt.Println(crossingTime)
}

Playground: https://play.golang.org/p/pXdGcinwxr-

Output:

5 [2 1 5 8 9]
5 [9 8 5 2 1]
15