русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Задача о восьми ферзях


Дата добавления: 2015-08-06; просмотров: 2033; Нарушение авторских прав


Задача о восьми ферзях — хорошо известный пример использования методов проб и ошибок и алгоритмов с возвратами. В 1850 г. эту задачу исследовал К.Ф. Гаусс, однако полностью он ее так и не решил, так как для подобных задач характерно отсутствие аналитического решения.

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

PROCEDURE Try(i: INTEGER);

BEGIN

инициация выбора положения i-гo ферзя;

REPEAT выбор очередного положения;

IF безопасно THEN BEGIN поставить ферзя;

IF i < 8 THEN BEGIN Try(i+1); (30)

IF неудача THEN BEGIN убрать ферзя END

END

END

UNTIL удача OR мест больше нет

END;

Далее необходимо остановиться на каком-либо представлении для данных. Поскольку из шахматных правил известно, что ферзь бьет все фигуры, находящиеся на той же самой вертикали, горизонтали или диагонали, то заключаем, что на каждой вертикали может находиться один и только один ферзь, поэтому при поиске места для i-го ферзя можно ограничить себя лишь i-й вертикалью. Таким образом, параметр i становится индексом вертикали, а процесс выбора возможного местоположения ограничивается восемью допустимыми значениями для индекса горизонтали j.

Остается решить вопрос: как представлять на доске эти восемь ферзей? Очевидно, доску вновь можно было бы представить в виде квадратной матрицы, однако это значительно бы усложнило проверку безопасности поля, что весьма нежелательно, посколькутакая операция выполняется очень часто. Поэтому остановимся на таком представлении данных, которое, насколько это возможно, упростило бы проверку. В этой ситуации лучше всего делать непосредственно доступной именно ту информацию, которая действительно важна и чаще всего используется. В нашем случае это не поля, занятые ферзями, а сведения о том, находится ли уже ферзь на данной горизонтали или диагонали (при этом уже известно, что на каждой k-йвертикали (1 £ k £ i) стоит только один ферзь). Исходя из этого переменные опишем следующим образом:



VAR х: ARRAY [1..8] OF INTEGER;

a: ARRAY [1..8] OF BOOLEAN;

b: ARRAY [b1..b2] OF BOOLEAN; (31)

c: ARRAY [c1..c2] OF BOOLEAN;

где

xi обозначает местоположение ферзя на i-й вертикали;

aj указывает, что на j-й горизонтали ферзя нет;

bk указывает, что на k-й å-диагонали ферзя нет;

ck указывает, что на k-й æ-диагонали ферзя нет.

Выбор границ индексов b1, b2, с1, с2 определяется исходя из способа вычисления индексов для b и с. На å-диагонали у всех полей постоянна сумма координат i и j, а на æ-диагонали постоянна их разность (соответствующие вычисления приведены в листинге 4). В соответствии с таким определением данных оператор поставить ферзя превращается в такие операторы:

x[i] := j; a[j] := FALSE; b[i+j] := FALSE; c[i-j] := FALSE; (32)

а оператор убрать ферзя — в такие:

a[j] := TRUE; b[i+j] := TRUE; c[i-j] := TRUE; (33)

Условие безопасно выполняется, если поле с координатами i, j лежит на горизонтали и вертикали, которые еще не заняты. Следовательно, ему соответствует логическое выражение

a[j] AND b[i+j] AND c[i-j]; (34)

Создание алгоритма закончено (полностью он представлен в листинге 4).

Листинг 4. Расстановка восьми ферзей (одно решение)

Program Queens;

VAR i: INTEGER; q: BOOLEAN;

a: ARRAY [1..8] OF BOOLEAN;

b: ARRAY [2..16] OF BOOLEAN;

c: ARRAY [-7..7] OF BOOLEAN;

x: ARRAY [1..8] OF INTEGER;

PROCEDURE Try(i: INTEGER; VAR q: BOOLEAN);

VAR j: INTEGER;

BEGIN j := 0;

REPEAT j := j+1; q:= FALSE;

IF (a[j] AND b[i+j]) AND c[i-j] THEN BEGIN

x[i] := j; a[j] := FALSE; b[i+j] := FALSE; c[i-j] := FALSE;

IF i < 8 THEN BEGIN Try(i+1, q);

IF NOT q THEN BEGIN

a[j] := TRUE; b[i+j] := TRUE; c[i-j] := TRUE;

END;

END

ELSE q := TRUE;

END;

UNTIL q OR (j = 8)

END;

 

BEGIN

FOR i := 1 TO 8 DO a[i] := TRUE;

FOR i := 2 TO 16 DO b[i] := TRUE;

FOR i := -7 TO 7 DO c[i] := TRUE;

Try(1,q);

FOR i := 1 TO 8 DO WriteLn(' Queen ',i,': ',x[i]);

ReadLn;

END.

 

m              
            m  
        m      
              m
  m            
      m        
          m    
    m          
 

 

Рис. 9. Одно из решений задачи о восьми ферзях

Программа дает решение х = (1, 5, 8, 6, 3, 7, 2, 4), которое изображено на рис. 9.

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

Такое обобщение получается исходя из того, что формирование возможных кандидатов происходит регулярным образом, гарантирующим, что ни один кандидат не встретится более чем один раз. Такое свойство алгоритма обеспечивается тем, что поиск идет по дереву кандидатов так, что каждая из его вершина проходится точно один раз. Это позволяет, если найдено и должным образом зафиксировано одно решение, просто переходить к следующему кандидату, предлагаемому упомянутым процессом систематического перебора. Общую схему такого процесса можно "вывести" из схемы (29):

PROCEDURE Try(i: INTEGER);

VAR k: INTEGER;

BEGIN

FOR k := 1 TO m DO BEGIN

выбор k-го кандидата; (35)

IF подходит THEN BEGIN его запись;

IF i < n THEN Try(i+1) ELSE печатать решения;

стирание записи

END

END

END;

Листинг 5.Расстановка восьми ферзей (все решения)

Program AllQueens;

VAR i: INTEGER;

a: ARRAY [1..8] OF BOOLEAN;

b: ARRAY [2..16] OF BOOLEAN;

c: ARRAY [-7..7] OF BOOLEAN;

x: ARRAY [1..8] OF INTEGER;

 

PROCEDURE print;

VAR k: INTEGER;

BEGIN

FOR k := 1 TO 8 DO Write(' ',x[k]);

END;

 

PROCEDURE Try(i: INTEGER);

VAR j: INTEGER;

BEGIN

FOR j := 1 TO 8 DO BEGIN

IF (a[j] AND b[i+j]) AND c[i-j] THEN BEGIN

x[i] := j;

a[j] := FALSE; b[i+j] := FALSE; c[i-j] := FALSE;

IF i < 8 THEN Try(i+1) ELSE BEGIN print; writeln; readln; END;

a[j] := TRUE; b[i+j] := TRUE; c[i-j] := TRUE;

END;

END;

END;

 

BEGIN

FOR i := 1 TO 8 DO a[i] := TRUE;

FOR i := 2 TO 16 DO b[i] := TRUE;

FOR i := -7 TO 7 DO c[i] := TRUE;

Try(1);

END.

При этом условие окончания в процессе выбора свелось к одному отношению k = m. Оператор повторения со словом REPEAT заменится на оператор цикла с FOR. При этом, как это не странно, поиск всех возможных решений выполняется более простой программой, чем в случае поиска одного-единственного решения*.

Обобщенный алгоритм, приведенный в программе на листинге 5, отыскивает 92 решения задачи о восьми ферзях. Однако принципиально различных решений всего 12 — наша программа не учитывает симметрию. В табл. 2 приведены первые 12 решений. Число n в правом столбце указывает, сколько раз проводилась проверка на "безопасность" поля. Среднее число для всех 92 решений равно 161.

Таблица 2. Двенадцать решений задачи о восьми ферзях

x1 x2 x3 x4 x5 x6 x7 x8 n

 

 



<== предыдущая лекция | следующая лекция ==>
Алгоритмы с возвратом | Задача оптимального выбора


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.325 сек.