Задача о Ханойских башнях...

КМ 23.05.2004 - 19:54 | и расстановке 8 ферзей на доске. Подскажите алгоритм решения на паскале.
ste 1 - 24.05.2004 - 08:10 | Рекурсия
NTFS 2 - 24.05.2004 - 11:24 | Только рекурсия!
NTFS 3 - 24.05.2004 - 11:25 | Поищи по Яндексу - где-то я видел алгоритм на C. А перевести на Паскаль уже не так сложно.
ПМ 4 - 24.05.2004 - 16:59 | Напиши сюда -- скину решение башен а что за задача с ферзями?
silly sad 5 - 24.05.2004 - 17:16 | алгоритм на паскале, музыка на русском, рация на броневике.
КМ 6 - 24.05.2004 - 18:25 | а может еще и задачу о перевозке подскажите?:) там вроде надо перевезти энн-ное количество монахов и каких-то головорезов на другой берег...или что-то в этом роде.
АМ 7 - 24.05.2004 - 18:53 | Про ханойские не помню, но 8 ферзей на доске - это фигня. В далёким 88 году будучи школьником на ROM-басике за один присест окучил безо всякой рекурсии. В чём проблема-то? Лень думать?
KM 8 - 24.05.2004 - 22:10 | Думать не лень, просто я уже кучу бумаги извела:)) Какдый раз запутываюсь%))
FWP 9 - 25.05.2004 - 08:24 | См. книгу Н.Вирт "Алгоритмы + Структуры данных = Программы"
Sabrian 10 - 26.05.2004 - 14:58 | Есть т блинов. И Есть 3 штыря - источник, приемник и темп. Необходимо отправить n-1 блин на 2 блин используя 3 как темп, потом нижний блин переложить на 3, после чего блины со 2-го отправить на 3 используя 1 как темп. Как видно алгоритм рекурсивный. MovBlin(sourse,dest) - перемещает блин с Sourse на Dest Hanoe(n,sourse,dest,temp) { if n=1 then { MovBlin(sourse,dest) } else { Hanoe(n-1,sourse,temp,dest) MovBlin(sourse,dest) Hanoe(n-1,temp,dest,source) } } proga { Hanoe(n,1,3,2) } Некий псевдокод, думаю все здесь понятно
Еще один 11 - 26.05.2004 - 19:26 | Видел решений пять задачи о Ханойских башнях, но рекурсивное - самое простое (хотя понять, почему оно правильно работает, не так легко) Вот вариант на паскале: var n:integer; procedure move(x,y,k:integer); begin if k=1 then writeln(x,' -> ',y) else begin move(x,6-x-y,k-1); move(x,y,1); move(6-x-y,y,k-1); end; end; begin writeln('Input n'); readln(n); move(1,3,n); readln; end. ---------------------------- процедура move перемещает со штыря с номером x на штырь с номером y k блинов штыри нумеруются от 1 до 3 если два известны,то номер третьего вычисляется как 6-x-y ------------------------------------ про ферзей задача решается методом перебора с возвратом (backtracking): простое наблюдение: в каждой горизонтали стоит ровно 1 ферзь пытаешься первого ферзя поместить на 1-ую горизонталь,..., i-го на i-ую горизонталь так чтобы они друг друга не били если i=8, то все хорошо иначе возвращаешься к предыдущему ферзю и пятаешься сдвинуть его вправо так чтобы он не бил предыдущих, если не получилось еще возвращаешься назад к предыдущим... Как только получилось сдвинуть ферзя, берешь следующего и пытаешься его поместить на горизонталь. Для решения этой задачи тебе нужен стек, массивы для проверки чтобы ферзи не били друг друга. удачи
archimag 12 - 27.05.2004 - 00:18 | Итак, 8 ферзей, код правда на С++, но думаю это не очень страшно:). Найдено 46 позиций. Основной цикл программы выполнялся 1965 раз. #inсludе <iostream> int cur_vert, count, success; int pos[8]; bool find_next_quen(); bool testing( int vert1, int vert2 ); void print_pos(); int main(int argc, char* argv[]) { for(;;) { count++; if( find_next_quen() ) { if( cur_vert == 7 ) { print_pos(); success++; pos[cur_vert] = 0; cur_vert--; } else cur_vert++; } else { if( cur_vert == 0 ) break; pos[cur_vert] = 0; cur_vert--; } } std::cout << "count cycle\t" << count << std::endl; std::cout << "success\t" << success << std::endl; return 0; } bool find_next_quen() { int old_quen_pos = pos[cur_vert]; pos[cur_vert]++; for(; pos[cur_vert] <= 8; pos[cur_vert] ++ ) if( cur_vert != 0 ) for( int vert = 0; vert < cur_vert; vert ++ ) { if( !testing( vert, cur_vert ) ) break; if( vert == ( cur_vert - 1 ) ) return true; } else { if( pos[cur_vert] != 8 ) { pos[cur_vert]++; return true; } else break; } pos[cur_vert] = old_quen_pos; return false; } bool testing( int vert1, int vert2 ) { if( pos[vert1] == pos[vert2] ) return false; if( abs( pos[vert1] - pos[vert2] ) == abs( vert1 - vert2 ) ) return false; return true; } void print_pos() { char v = 'a'; int vert = 0; for( ; vert < 7; v++, vert++ ) std::cout << v << pos[vert]<< ", "; std::cout << v << pos[7]<< std::endl; }
Еще один 13 - 27.05.2004 - 15:11 | вообще-то должно быть найдено 92 позиции (если я точно помню), но никак не 46. Может ты убираешь симметричные?
archimag 14 - 27.05.2004 - 16:58 | Это действительно так :-( В данном коде присутствуют две ошибки, которые я на быструю руку не заметил, а увидел только сегодня утром. Из-за этих ошибок программа находит не все возможные позиции. В функции find_next_quen необходимо в сравнение pos[cur_vert] != 8 заменить 8 на 9, и в том же операторе if, убрать лишнюю строчку pos[cur_vert]++. В итоге, изменённая версия программы находит 92 решения за 3929 циклов. Вот такой вот косяк :((.
Zanzamar 15 - 29.05.2004 - 14:03 | Помнится в незапамятные времена у нашего уважаемого модератора была такая оч-чень хорошая книжка "Программирование игр и головоломок", автора не помню. Сергей, напиши людям данные той книжки, пусть приобщатся к дао ! :)
ПМ 16 - 31.05.2004 - 10:25 | Кстати, никто на вскидку не вспомнит алгоритм генерации всех возможных перестановок? Ведь по сути задача про ферзей именно в этом и заключается
Еще один 17 - 31.05.2004 - 13:10 | Существует несколько алгоритмов генерации перестановок: лексикографический порядок, антилексикографический, генерация след перестановки только одной траспозицией, и др. Приведу простой, может неоптимальный алгоритм: const n=5; var used:array[1..n] of 0..1; {множество чисел 1..n, used[i]=1 если цифра i-использована} a:array[1..n] of byte; {собственно сама перестановка} procedure gen(x:byte); var i:integer; begin if x=n+1 then begin for i:=1 to n do write(a[i],' '); writeln; end else for i:=1 to n do if used[i]=0 then begin used[i]:=1; a[x]:=i; gen(x+1); used[i]:=0; end; end; begin fillchar(used,sizeof(used),0); {обнуляем used} gen(1); end.
archimag 18 - 01.06.2004 - 13:49 | Ну, в задаче про ферзей, я бы не советовал использовать алгоритм генерации ВСЕХ возможных перестановок, уж больно цифра неприличная получается :о))
ПМ 19 - 08.06.2004 - 21:59 | 18 - po-noemu, 8!=32000(primerno). Esli napisat' normal'nuyu funkciyu proverki, to ty daje ne zametish skol'ko programma dumala.
silly sad 20 - 09.06.2004 - 09:47 | все расстановки ферзей это Ц из 64 по 8 - с каких это пор это число стало равно 8! ??? это только современные супер-пупер програмисты могли открыть.
archimag 21 - 09.06.2004 - 12:31 | 19: 8!=40320, если быть точным, и не заметишь ты этого только на своём можном компьютере. Правда так можно записать короче: #inсludе <algorithm> #inсludе <iostream> using namespace std; int pos[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int counter = 0; void test(); int main() { while( next_permutation( pos, pos + 8 ) ) test(); cout << "position count:\t" << counter << endl; return 0; } void test() { for( int i = 0; i < 8; i++ ) for( int j = i+1; j < 8; j++ ) if( abs( i - j ) == abs( pos[i] - pos[j] ) ) return; counter++; } Вот и вся программа

>>