Конкурс на решение задачи!, Переправа через реку... ну очень широкую |
1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!
Конкурс на решение задачи!, Переправа через реку... ну очень широкую |
APAL |
Сообщение
#1
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Каюсь, иногда играю в комп. игры. И вот в "Космических рейнджерах" был квест с этой задачкой:
Дано: Река, лодка вместимостью 2 человека, два берега. Условия: На одном берегу 4 человека. Первый может проплыть на лодке на другой берег за 1 час, второй за 2 часа, третий за 5 часов, четвертый за 10 часов. Если в лодке два человека то она проплывет за время "самого медленного пассажира". Задача: Необходимо перевести всех людей на другой берег не более чем за 18 часов! Сходу решить мне не удалось - написал на Паскале. Квест прошел. Свой вариант выложу по окончанию времени конкурса. Условия конкурса: Свои решения присылать на "мыло": apalprival @ narod . ru. Срок проведения 2 недели, т.е. до 7 февраля 2005 г. (это еще можно обсудить) Номинации: 1. Самое первое правильное решение. 2. Самое короткое-оптимальное решение. 3. Самое изощренное решение. Каждому победителю +1 к повышению рейтинга на форуме. Свои решения присылайте в архивированном виде! И не забудьте включить в архив исполняемый модуль (*.EXE), дабы избежать конфликтов компиляторов. -------------------- |
Altair |
Сообщение
#2
|
||
Ищущий истину Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Опровержение такой возможности: (ИМХО)
-------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
||
APAL |
Сообщение
#3
|
||
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Oleg_Z, не совсем все так просто... вот один из вариантов решения:
Итог - 17 часов на переброску четырех человек. Сообщение отредактировано: Oleg_Z - -------------------- |
||
Altair |
Сообщение
#4
|
||
Ищущий истину Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: 45 |
да, все понял.... я не учел что
-------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
||
Junkie |
Сообщение
#5
|
Гость |
я наверное тупой... но по-моему невозможно перевезти людей за 18 часов... минимальное время - 19 часов... разве-что пустую лодка сама может приплыть обратно на другой берег....
Первый едет с 4-ым на берег 2 +10 часов Первый возвращается на берег 1 +1 час Первый едет с 3-ым на берег 2 +5 часов Первый возвращается на берег 1 +1 час Первый едет с 2-ым на берег 2 +2 часов 10+1+5+1+2=19 Сообщение отредактировано: volvo - |
volvo |
Сообщение
#6
|
Гость |
Junkie
Возможно и не только за 18, а за 17 - точно. Может быть, можно и за меньшее время. Кто знает... |
GoodWind |
Сообщение
#7
|
Автооответчик Группа: Пользователи Сообщений: 1 188 Пол: Мужской Реальное имя: Александр Репутация: 16 |
Apal, ты мой герой !!!!
я над этим квестом 3-е суток парился, так и не решил :no: стока денег и респекту потерял... -------------------- Неадекватная чушь может быть адекватным ответом на неадекватный вопрос. Понятно или разжевать?
|
Altair |
Сообщение
#8
|
Ищущий истину Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Цитата я наверное тупой... но по-моему невозможно перевезти людей за 18 часов... минимальное время - 19 часов... разве-что пустую лодка сама может приплыть обратно на другой берег.... Нет, просто ты забыл, что оттуда может вернуться кто-то кто уже там ;) -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
APAL |
Сообщение
#9
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Цитата(GoodWind @ 25.01.05 20:28) Apal, ты мой герой !!!! я над этим квестом 3-е суток парился, так и не решил :no: стока денег и респекту потерял... Я тоже немного посидел и вот сделал прогу которая сама все решила... :D А задачка хорошая, мне понравилась! -------------------- |
FreeMan |
Сообщение
#10
|
- Группа: Пользователи Сообщений: 480 Пол: Мужской Репутация: 4 |
Я Рейнджеров купил, как только они вышли. Этот квест проходил тупым перебором. Потом прошёл (17 часов). Кстати, там можно делать свои квесты (есть прога на сайте производителя).
-------------------- бб
|
APAL |
Сообщение
#11
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
FreeMan - флейм! Давайте не отклоняться от темы.
Дамы и господа! Неужели все так сложно? Или сроки проведения конкурса продлить? Еще ни одного письма с решением не получил! P.S.: Мозги надо иногда разминать... -------------------- |
APAL |
Сообщение
#12
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Первое решение поступило.
-------------------- |
Jahnerus |
Сообщение
#13
|
Уникальный Группа: Пользователи Сообщений: 64 Пол: Мужской Репутация: 2 |
APAL
:D Жди последнего дня ... тебя решениями завалят ... всё же как обычно делается в последний день. (точнее в последнюю ночь) -------------------- Век живи, век учи С © by Jahnerus
|
Jahnerus |
Сообщение
#14
|
Уникальный Группа: Пользователи Сообщений: 64 Пол: Мужской Репутация: 2 |
APAL
Письмо моё получил? -------------------- Век живи, век учи С © by Jahnerus
|
APAL |
Сообщение
#15
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Цитата(Jahnerus @ 3.02.05 21:00) Да, письмо получил. От Volvo тоже пришло второе решение. -------------------- |
APAL |
Сообщение
#16
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
Итак, можно подводить итог!
К сожалению конкурсантов всего двое. Я рад такому бурному и оживленному решению поставленной задачи. (камень в огород тех кто не принял участи) -------------------- |
APAL |
Сообщение
#17
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
1. Самое первое правильное решение
VOLVO Исходный код const size = 4; type all_type = array[1 .. size] of integer; pair = array[1 .. 2] of word; const s1_len = 6; step_one: array[1 .. s1_len] of pair = ((1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)); s2_len = 2; step_two: array[1 .. s2_len] of word = (1, 2); s3_len = 3; step_three: array[1 .. s3_len] of pair = ((1, 2), (2, 3), (1, 3)); s4_len = 3; step_four: array[1 .. s4_len] of word = (1, 2, 3); s5_len = 1; step_five: array[1 .. s5_len] of pair = ((1, 2)); const right: all_type = (1, 2, 5, 10); left: all_type = (-1, -1, -1, -1); procedure compact(var x: all_type); var T: all_type; i, next: byte; begin move(x, T, sizeof(x)); next := 0; for i := 1 to size do if T[i] <> -1 then begin inc(next); x[next] := T[i] end; for i := succ(next) to size do x[i] := -1; end; procedure append(var x: all_type; a: word); var i: integer; begin i := 1; while x[i] <> -1 do inc(i); x[i] := a; end; function max(a, b: word): word; begin max := a; if b > a then max := b end; function get_two(by: pair; var x: pair): word; begin { from right } x[1] := right[by[1]]; right[by[1]] := -1; x[2] := right[by[2]]; right[by[2]] := -1; compact(right); get_two := max(x[1], x[2]) end; function get_one(by: word; var x: word): word; begin { from left } x := left[by]; left[by] := -1; compact(left); get_one := x end; procedure print_array(x: all_type); var i: byte; begin for i := 1 to size do if x[i] <> -1 then write(x[i]:4); writeln end; var min1, min2, min3, min4, min5: byte; mp: pair; path, T: word; procedure create_path; var right0, right1, right2, right3, right4, left0, left1, left2, left3, left4: all_type; s1, s2, s3, s4: word; p1, p2, p3, p4, p5: byte; min_path: word; begin path := 0; min_path := maxInt; move(left, left0, sizeof(left)); move(right, right0, sizeof(right)); for p1 := 1 to s1_len do begin move(left0, left, sizeof(left)); move(right0, right, sizeof(right)); path := get_two(step_one[p1], mp); append(left, mp[1]); append(left, mp[2]); s1 := path; move(left, left1, sizeof(left)); move(right, right1, sizeof(right)); for p2 := 1 to s2_len do begin path := s1; move(left1, left, sizeof(left)); move(right1, right, sizeof(right)); inc(path, get_one(step_two[p2], T)); append(right, T); s2 := path; move(left, left2, sizeof(left)); move(right, right2, sizeof(right)); for p3 := 1 to s3_len do begin path := s2; move(left2, left, sizeof(left)); move(right2, right, sizeof(right)); inc(path, get_two(step_three[p3], mp)); append(left, mp[1]); append(left, mp[2]); s3 := path; move(left, left3, sizeof(left)); move(right, right3, sizeof(right)); for p4 := 1 to s4_len do begin path := s3; move(left3, left, sizeof(left)); move(right3, right, sizeof(right)); inc(path, get_one(step_four[p4], T)); append(right, T); s4 := path; move(left, left4, sizeof(left)); move(right, right4, sizeof(right)); for p5 := 1 to s5_len do begin path := s4; move(left4, left, sizeof(left)); move(right4, right, sizeof(right)); inc(path, get_two(step_five[p5], mp)); append(left, mp[1]); append(left, mp[2]); if min_path > path then begin min1 := p1; min2 := p2; min3 := p3; min4 := p4; min5 := p5; min_path := path; end; end; end; end; end; end; writeln('min path len = ', min_path); move(left0, left, sizeof(left)); move(right0, right, sizeof(right)); end; begin write('right'); print_array(right); write('left'); print_array(left); writeln('starting...'); create_path; {#1} path := get_two(step_one[min1], mp); append(left, mp[1]); append(left, mp[2]); writeln('right > left: ', mp[1]:4, mp[2]:4, ' time = ', path); {#2} inc(path, get_one(step_two[min2], T)); append(right, T); writeln('left > right: ', T:4, ' time = ', path); {#3} inc(path, get_two(step_three[min3], mp)); append(left, mp[1]); append(left, mp[2]); writeln('right > left: ', mp[1]:4, mp[2]:4, ' time = ', path); {#4} inc(path, get_one(step_four[min4], T)); append(right, T); writeln('left > right: ', T:4, ' time = ', path); {#5} inc(path, get_two(step_five[min5], mp)); append(left, mp[1]); append(left, mp[2]); writeln('right > left: ', mp[1]:4, mp[2]:4, ' time = ', path); end. -------------------- |
APAL |
Сообщение
#18
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
2. Самое короткое-оптимальное решение.
Jahnerus Исходный код {© by Jahnerus} type ma3x=array[1..4] of byte; ma3x_moves=array[1..5,1..2] of byte; ma3x_bool=array[1..4] of boolean; const time:ma3x=(1,2,5,10); var ident:ma3x_bool; moves:ma3x_moves; f:text; {------------ Podschet vremeni --------------} function get_time(moves:ma3x_moves):byte; var i,tmp:byte; begin tmp:=0; for i:=1 to 5 do begin if time[moves[i,1]]>time[moves[i,2]] then tmp:=tmp+time[moves[i,1]] else tmp:=tmp+time[moves[i,2]]; end; get_time:=tmp; end; {------- Proverka vremeni i vivod dannih ---------} procedure check(moves:ma3x_moves); var i:byte; begin if get_time(moves)<=18 then begin for i:=1 to 5 do begin if i mod 2 = 0 then write(f,' ',time[moves[i,1]],' ') else write(f,time[moves[i,1]],'-',time[moves[i,2]]); end; writeln(f,' za ',get_time(moves),' chasov'); end; end; {------------- Peredvijeniya lodki ------------} procedure boat_moves(moves:ma3x_moves; n:byte; ident:ma3x_bool; flag:boolean); var i,j:byte; begin if n<=5 then begin for i:=1 to 4 do begin if (ident[i]) xor (flag) then begin moves[n,1]:=i; ident[i]:=flag; if flag then begin for j:=i+1 to 4 do begin if not(ident[j]) then begin moves[n,2]:=j; ident[j]:=flag; boat_moves(moves,n+1,ident,not(flag)); ident[j]:=not(flag); end; end; end else begin moves[n,2]:=i; boat_moves(moves,n+1,ident,not(flag)); end; ident[i]:=not(flag); end; end; end else check(moves); end; {------------ Osnovnoy blok --------------} begin assign(f,'out.txt'); rewrite(f); boat_moves(moves,1,ident,true); close(f); end. -------------------- |
APAL |
Сообщение
#19
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
3. Самое изощренное решение.
VOLVO Исходный код uses crt; const players = 4; { players = 6; } type all_type = array[1 .. players] of integer; pair = array[1 .. 2] of word; const right: all_type = (1, 10, 5, 2); { (1, 10, 5, 2, 11, 3); } left: all_type = (-1, -1, -1, -1); { (-1, -1, -1, -1, -1, -1); } type PTForward = ^step_forward; step_forward = array[1 .. maxInt div sizeof(pair)] of pair; PTBackward = ^step_backward; step_backward = array[1 .. maxint div sizeof(word)] of word; type TDirection = (drForward, drBackward); TOptimized = Record save_left, save_right: all_type; save_path: integer; len: word; case going: TDirection of drForward : (arr_f: PTForward); drBackward: (arr_b: PTBackward); End; TArrOptimized = ^arrOptimized; arrOptimized = array[0 .. pred(maxint) div sizeof(TOptimized)] of TOptimized; var opt_arr_index: integer; opt_arr: TArrOptimized; function count_forward(n: byte): byte; begin if n <= 1 then count_forward := 0 else count_forward := count_forward(pred(n)) + pred(n) end; function moves(n: byte): byte; begin moves := succ((n - 2) shl 1) end; procedure generate; function generate_forward(right: integer; var arr: PTForward): integer; var i, j, count: integer; begin count := count_forward(right); getmem(arr, count*sizeof(pair)); count := 0; for i := 1 to pred(right) do for j := succ(i) to right do begin inc(count); arr^[count][1] := i; arr^[count][2] := j; end; generate_forward := count; end; function generate_backward(left: integer; var arr: PTBackward): integer; var count: integer; begin getmem(arr, left*sizeof(word)); for count := 1 to left do arr^[count] := count; generate_backward := count; end; var on_right: integer; begin getmem( opt_arr, succ(moves(players)) * sizeof(TOptimized) ); opt_arr_index := 0; move(left, opt_arr^[0].save_left, sizeof(left)); move(right, opt_arr^[0].save_right, sizeof(right)); opt_arr^[0].save_path := 0; on_right := players; while on_right > 0 do begin inc(opt_arr_index); with opt_arr^[opt_arr_index] do begin going := drForward; len := generate_forward(on_right, arr_f); end; dec(on_right, 2); if on_right = 0 then break; inc(opt_arr_index); with opt_arr^[opt_arr_index] do begin going := drBackward; len := generate_backward(players-on_right, arr_b); end; inc(on_right) end; end; procedure compact_array(var x: all_type); var T: all_type; i, next: byte; begin move(x, T, sizeof(x)); next := 0; for i := 1 to players do if T[i] <> -1 then begin inc(next); x[next] := T[i] end; for i := succ(next) to players do x[i] := -1; end; procedure append_array(var x: all_type; const n: byte; var avar); var a: pair absolute avar; i, j: integer; begin i := 1; while x[i] <> -1 do inc(i); for j := 0 to pred(n) do x[i + j] := a[succ(j)] end; procedure print_array(x: all_type); var i: byte; begin for i := 1 to players do if x[i] <> -1 then write(x[i]:4); writeln end; function get_number(var from: all_type; const n: byte; var byvar, xvar): word; var x: pair absolute xvar; by: pair absolute byvar; i: byte; begin for i := 1 to n do begin x[i] := from[by[i]]; from[by[i]] := -1; end; compact_array(from); get_number := x[1]; if (n = 2) and (x[2] > x[1]) then get_number := x[2] end; var mins, ps: PTBackward; mp: pair; path, T: word; const min_path: integer = maxInt; procedure go_for_it(n: integer); var p, i: integer; begin move(left, opt_arr^[n].save_left, sizeof(left)); move(right, opt_arr^[n].save_right, sizeof(right)); for p := 1 to opt_arr^[n].len do begin path := opt_arr^[pred(n)].save_path; move(opt_arr^[pred(n)].save_left, left, sizeof(left)); move(opt_arr^[pred(n)].save_right, right, sizeof(right)); ps^[n] := p; with opt_arr^[n] do case going of drForward: begin inc(path, get_number(right, 2, arr_f^[p], mp)); append_array(left, 2, mp) end; drBackward: begin inc(path, get_number(left, 1, arr_b^[p], T)); append_array(right, 1, T) end; end; if n = opt_arr_index then begin if min_path > path then begin move(ps^[1], mins^[1], n * sizeof(word)); min_path := path end; move(opt_arr^[n].save_left, left, sizeof(left)); move(opt_arr^[n].save_right, right, sizeof(right)); end else begin opt_arr^[n].save_path := path; move(left, opt_arr^[n].save_left, sizeof(left)); move(right, opt_arr^[n].save_right, sizeof(right)); go_for_it(succ(n)) end; end; end; var i: integer; begin clrscr; write('right'); print_array(right); write('left'); print_array(left); writeln; generate; getmem(mins, opt_arr_index*sizeof(word)); getmem(ps, opt_arr_index*sizeof(word)); go_for_it(1); move(opt_arr^[0].save_left, left, sizeof(left)); move(opt_arr^[0].save_right, right, sizeof(right)); path := 0; for i := 1 to opt_arr_index do with opt_arr^[i] do begin case going of drForward: begin inc(path, get_number(right, 2, arr_f^[mins^[i]], mp)); append_array(left, 2, mp); writeln('right > left: ', mp[1]:4, mp[2]:4, ' time = ', path); freemem(arr_f, len*sizeof(pair)) end; drBackward: begin inc(path, get_number(left, 1, arr_b^[mins^[i]], T)); append_array(right, 1, T); writeln('left > right: ', T:4, ' time = ', path); freemem(arr_b, len*sizeof(word)) end; end end; freemem(ps, opt_arr_index*sizeof(word)); freemem(mins, opt_arr_index*sizeof(word)); freemem( opt_arr, succ(moves(players)) * sizeof(TOptimized) ); end. -------------------- |
APAL |
Сообщение
#20
|
Смотрю... Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: 6 |
И наконец мой вариант:
Uses MyServis {из этого модуля используется только функция IntToStr - преобразование числа в строку}; -------------------- |
Текстовая версия | 11.01.2025 5:12 |