Ответ 1
Существует весь PDF (альтернативная ссылка), который решает общий случай этой задачи (в формальном доказательстве).
Четыре человека должны пересечь мост ночью. Любая сторона, которая пересекает, один или два человека, должна носить с собой фонарик. Фонарик должен идти назад и вперед; его нельзя бросать и т.д. Каждый человек идет с другой скоростью. Один переход занимает 1 минуту, еще 2 минуты, еще 5 и последние 10 минут. Если двое мужчин пересекаются, они должны ходить медленнее. Нет никаких трюков - мужчины все начинают с одной стороны, фонарик не может сиять на большом расстоянии, никто не может нести и т.д.
И вопрос в том, что самое быстрое, с чем они могут справиться. В основном я ищу некоторый обобщенный подход к этой проблеме. Мне сказал мой друг, что это может быть решена с помощью серии Фибоначчи, но решение не работает для всех.
Обратите внимание, что это не домашний труд.
Существует весь PDF (альтернативная ссылка), который решает общий случай этой задачи (в формальном доказательстве).
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.
В общем, самая большая проблема/самые медленные люди всегда должны быть собраны вместе, и достаточные поездки из самых быстрых, чтобы иметь возможность возвращать свет каждый раз, не используя медленный ресурс.
Я бы решил эту проблему, разместив поддельную рекламную кампанию на Dice.com, а затем задав этот вопрос в интервью, пока кто-то не поправится.
Согласно Википедии
Известно, что головоломка появилась еще в 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
Здесь ответ в 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}"
Еще одна реализация 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
-------------------------
Исчерпывающий поиск всех возможностей прост с таким небольшим проблемным пространством. Сначала будет работать ширина или глубина. Это простая проблема с CS.
Я предпочитаю проблемы миссионера и каннибала себе
17 - очень распространенный вопрос
- > 1-2 = 2
< - 2 = 2
- > 5,10 = 10 (ни один из них не должен возвращаться)
< - 1 = 1
- > 1,2 = 2
все с другой стороны
total = 2 + 2 + 10 + 1 + 2 = 17
обычно люди получают это как 19 в первой попытке
Я определил возможные решения алгебраически и вышел с самым быстрым временем. и присваивая алгебре список 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 раза, самый быстрый идет один раз, а самый медленный идет со вторым самым медленным.
Простой алгоритм: предположим, что "N" - это число людей, которые могут пересекаться в одно и то же время, и один человек должен переходить обратно с факелом
Вот пример python script, который делает это: https://github.com/meowbowgrr/puzzles/blob/master/bridgentorch.py