Мозаика

Четыре человека должны пересечь мост ночью. Любая сторона, которая пересекает, один или два человека, должна носить с собой фонарик. Фонарик должен идти назад и вперед; его нельзя бросать и т.д. Каждый человек идет с другой скоростью. Один переход занимает 1 минуту, еще 2 минуты, еще 5 и последние 10 минут. Если двое мужчин пересекаются, они должны ходить медленнее. Нет никаких трюков - мужчины все начинают с одной стороны, фонарик не может сиять на большом расстоянии, никто не может нести и т.д.

И вопрос в том, что самое быстрое, с чем они могут справиться. В основном я ищу некоторый обобщенный подход к этой проблеме. Мне сказал мой друг, что это может быть решена с помощью серии Фибоначчи, но решение не работает для всех.

Обратите внимание, что это не домашний труд.

Ответы

Ответ 2

17 минут - это классический вопрос MS.

1,2 => 2 minutes passed.
1 retuns => 3 minutes passed.
5,10 => 13 minutes passed.
2 returns => 15 minutes passed.
1,2 => 17 minute passed.

В общем, самая большая проблема/самые медленные люди всегда должны быть собраны вместе, и достаточные поездки из самых быстрых, чтобы иметь возможность возвращать свет каждый раз, не используя медленный ресурс.

Ответ 3

Я бы решил эту проблему, разместив поддельную рекламную кампанию на Dice.com, а затем задав этот вопрос в интервью, пока кто-то не поправится.

Ответ 4

Согласно Википедии

Известно, что головоломка появилась еще в 1981 году в книге "Супер стратегии для головоломок и игр". В этой версии головоломки A, B, C и D берут 5, 10, 20 и 25 минут, соответственно, чтобы пересечься, а время составляет 60 минут

Этот вопрос был популяризирован после его появления в книге "Как бы вы переместили гору Фудзи?"

вопрос может быть обобщен для N людей с различным индивидуальным временем, затраченным на переход через мост.

Нижеприведенная программа работает для общего N людей и их времени.

class Program
{
    public static int TotalTime(List<int> band, int n)
    {
        if (n < 3)
        {
            return band[n - 1];
        }
        else if (n == 3)
        {
            return band[0] + band[1] + band[2];
        }
        else
        {
            int temp1 = band[n - 1] + band[0] + band[n - 2] + band[0];
            int temp2 = band[1] + band[0] + band[n - 1] + band[1];

            if (temp1 < temp2)
            {
                return temp1 + TotalTime(band, n - 2);
            }
            else if (temp2 < temp1)
            {
                return temp2 + TotalTime(band, n - 2);
            }
            else
            {
                return temp2 + TotalTime(band, n - 2);
            }
        }
    }

    static void Main(string[] args)
    {
        // change the no of people crossing the bridge
        // add or remove corresponding time to the list
        int n = 4; 

        List<int> band = new List<int>() { 1, 2, 5, 10 };

        band.Sort();

        Console.WriteLine("The total time taken to cross the bridge is: " + Program.TotalTime(band, n));
        Console.ReadLine();
    }
}

ВЫВОД:

Общее время прохождения моста: 17

Для <

int n = 5; 
List<int> band = new List<int>() { 1, 2, 5, 10, 12 };

ВЫВОД:

Общее время, затраченное на пересечение моста: 25

Для

int n = 4; 
List<int> band = new List<int>() { 5, 10, 20, 25 };

ВЫВОД Общее время прохождения моста: 60 ​​

Ответ 5

Здесь ответ в ruby:

@values = [1, 2, 5, 10]
# @values = [1, 2, 5, 10, 20, 25, 30, 35, 40]
@values.sort!
@position = @values.map { |v| :first }
@total = 0

def send_people(first, second)
  first_time = @values[first]
  second_time = @values[second]

  @position[first] = :second
  @position[second] = :second

  p "crossing #{first_time} and #{second_time}"

  first_time > second_time ? first_time : second_time
end

def send_lowest
  value = nil
  @values.each_with_index do |v, i|
    if @position[i] == :second
      value = v
      @position[i] = :first
      break
    end
  end

  p "return #{value}"
  return value
end


def highest_two
  first = nil
  second = nil

  first_arr = @position - [:second]

  if (first_arr.length % 2) == 0
    @values.each_with_index do |v, i|
      if @position[i] == :first
        first = i unless first
        second = i if !second && i != first
      end

      break if first && second
    end
  else
    @values.reverse.each_with_index do |v, i|
      real_index = @values.length - i - 1
      if @position[real_index] == :first
        first = real_index unless first
        second = real_index if !second && real_index != first
      end

      break if first && second
    end
  end

  return first, second
end

#we first send the first two
@total += send_people(0, 1)
#then we get the lowest one from there
@total += send_lowest
#we loop through the rest with highest 2 always being sent
while @position.include?(:first)
  first, second = highest_two
  @total += send_people(first, second)
  @total += send_lowest if @position.include?(:first)
end

p "Total time: #{@total}"

Ответ 6

Еще одна реализация Ruby, вдохновленная решением @roc-khalil

@values = [1,2,5,10]
# @values = [1,2,5,10,20,25]
@left = @values.sort
@right = []
@total_time = 0

def trace(moving)
  puts moving
  puts "State: #{@left} #{@right}"
  puts "Time: #{@total_time}"
  puts "-------------------------"
end

# move right the fastest two
def move_fastest_right!
  fastest_two = @left.shift(2)
  @right = @right + fastest_two
  @right = @right.sort
  @total_time += fastest_two.max
  trace "Moving right: #{fastest_two}"
end

# move left the fastest runner
def move_fastest_left!
  fastest_one = @right.shift
  @left << fastest_one
  @left.sort!
  @total_time += fastest_one
  trace "Moving left: #{fastest_one}"
end

# move right the slowest two
def move_slowest_right!
  slowest_two = @left.pop(2)
  @right = @right + slowest_two
  @right = @right.sort
  @total_time += slowest_two.max
  trace "Moving right: #{slowest_two}"
end

def iterate!
  move_fastest_right!
  return if @left.length == 0

  move_fastest_left!
  move_slowest_right!
  return if @left.length == 0

  move_fastest_left!
end

puts "State: #{@left} #{@right}"
puts "-------------------------"
while @left.length > 0
  iterate!
end

Вывод:

State: [1, 2, 5, 10] []
-------------------------
Moving right: [1, 2]
State: [5, 10] [1, 2]
Time: 2
-------------------------
Moving left: 1
State: [1, 5, 10] [2]
Time: 3
-------------------------
Moving right: [5, 10]
State: [1] [2, 5, 10]
Time: 13
-------------------------
Moving left: 2
State: [1, 2] [5, 10]
Time: 15
-------------------------
Moving right: [1, 2]
State: [] [1, 2, 5, 10]
Time: 17
-------------------------

Ответ 7

Исчерпывающий поиск всех возможностей прост с таким небольшим проблемным пространством. Сначала будет работать ширина или глубина. Это простая проблема с CS.

Я предпочитаю проблемы миссионера и каннибала себе

Ответ 8

17 - очень распространенный вопрос

- > 1-2 = 2
< - 2 = 2
- > 5,10 = 10 (ни один из них не должен возвращаться)
< - 1 = 1
- > 1,2 = 2

все с другой стороны
total = 2 + 2 + 10 + 1 + 2 = 17

обычно люди получают это как 19 в первой попытке

Ответ 9

Я определил возможные решения алгебраически и вышел с самым быстрым временем. и присваивая алгебре список A, B, C, D, где A - наименьший, а D - самый большой формула для кратчайшего времени равна B + A + D + B + B или 3B + A + D или в словесных выражениях, сумму вторых самых быстрых раз 3 и добавить с самыми быстрыми и самыми медленными.

глядя на программу, был также вопрос об увеличенных деталях. Хотя я не прошел через это, но я догадываюсь, что формула все еще применяется, просто добавьте до тех пор, пока все предметы со вторым пунктом раз 3 и суммой всего, кроме 2-х самых медленных времен. например так как 4 элемента - 3 х второй + первый и четвертый. то 5 предметов - это 3 х второй + первый, третий и пятый. хотел бы проверить это с помощью программы.

Также я просто посмотрел на вышеприведенный формат pdf, поэтому для большего количества предметов это сумма 3 x секунд + самая быстрая + сумма наименьшей из каждой последующей пары.

глядя на шаги для оптимизированного решения, идея -right - для двух предметов, идущих вправо, самый быстрый - 1-й и 2-й, -left - тогда плюс самый быстрый возврат для одного предмета - это самый быстрый предмет -right - принесите самые медленные 2 предмета, которые будут учитывать только самый медленный предмет и игнорировать второй самый медленный. -left - второй самый быстрый предмет. -final right - 1-й и 2-й наиболее быстрые результаты

так что снова суммирование = 2-й самый быстрый идет 3 раза, самый быстрый идет один раз, а самый медленный идет со вторым самым медленным.

Ответ 10

Простой алгоритм: предположим, что "N" - это число людей, которые могут пересекаться в одно и то же время, и один человек должен переходить обратно с факелом

  • При перемещении людей с первой стороны на вторую сторону предпочтение следует отдавать "медленным ходокам" N
  • Всегда используйте самый быстрый ходок, чтобы сжечь факел со второй стороны на первую сторону.
  • При перемещении людей с первой стороны на вторую сторону учитывайте, кто вернет факел на следующем шаге. Если скорость ведущего факела на следующем шаге будет равна самому быстрому ходоку, среди "самых медленных ходоков" N на текущем шаге вместо того, чтобы выбрать "N" самый медленный ходок, как указано в "1", выберите "N" быстрые ходунки"

Вот пример python script, который делает это: https://github.com/meowbowgrr/puzzles/blob/master/bridgentorch.py