на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Государственный комитет Российской Федерации по высшему и среднеспециальному образованию Красноярский Государственный Технический Университет

Курсовая работа

по курсу Математическая логика и теория алгоритмов

Выполнил студент гр. ВТ27-4

Попов А.В. Проверила: Пестунова Т.М. 1998 Содержание. 1. Постановка задачи (стр.3). 2. Построение модели (стр.3). 3. Описание алгоритма (стр.4). 4. Доказательство правильности алгоритма (стр.7). 5. Блок-схема алгоритма (стр.8). 6. Описание переменных и программа (стр.9). 7. Расчёт вычислительной сложности (стр.11). 8. Тестирование (стр.11). 9. Список литературы (стр.12). Постановка задачи. Перечислить все способы расстановки n ферзей на шахматной доске n на n, при которых они не бьют друг друга. Построение модели. Очевидно, на каждой из n горизонталей должно стоять по ферзю. Будем называть k-позицией (для k = 0, 1,...,n) произвольную расстановку k ферзей на k нижних горизонталях (ферзи могут бить друг друга). Нарисуем "дерево позиций": его корнем будет единственная 0-позиция, а из каждой k-позиции выходит n стрелок вверх в (k+1)-позиции. Эти n позиций отличаются положением ферзя на (k+1)-ой горизонтали. Будем считать, что расположение их на рисунке соответствует положению этого ферзя: левее та позиция, в которой ферзь расположен левее.

Дерево позиций для n = 2

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n Данное дерево представлено только для наглядности и простоты представления для n=2. Среди позиций этого дерева нам надо отобрать те n-позиции, в которых ферзи не бьют друг друга. Программа будет "обходить дерево" и искать их. Чтобы не делать лишней работы, заметим вот что: если в какой-то k-позиции ферзи бьют друг друга, то ставить дальнейших ферзей смысла нет. Поэтому, обнаружив это, мы будем прекращать построение дерева в этом направлении. Точнее, назовем k-позицию допустимой, если после удаления верхнего ферзя оставшиеся не бьют друг друга. Наша программа будет рассматривать только допустимые позиции. Описание алгоритма. Разобьем задачу на две части: (1) обход произвольного дерева и (2) реализацию дерева допустимых позиций. Сформулируем задачу обхода произвольного дерева. Будем считать, что у нас имеется Робот, который в каждый момент находится в одной из вершин дерева. Он умеет выполнять команды: вверх_налево (идти по самой левой из выходящих вверх стрелок) вправо (перейти в соседнюю справа вершину) вниз (спуститься вниз на один уровень) вверх_налево вправо вниз и проверки, соответствующие возможности выполнить каждую из команд, называемые "есть_сверху", "есть_справа", "есть_снизу" (последняя истинна всюду, кроме корня). Обратите внимание, что команда "вправо" позволяет перейти лишь к "родному брату", но не к "двоюродному". Будем считать, что у Робота есть команда "обработать" и что его задача - обработать все листья (вершины, из которых нет стрелок вверх, то есть где условие "есть_сверху" ложно). Для нашей шахматной задачи команде обработать будет соответствовать проверка и печать позиции ферзей. Доказательство правильности приводимой далее программы использует такие определения. Пусть фиксировано положение Робота в одной из вершин дерева. Тогда все листья дерева разбиваются на три категории: над Роботом, левее Робота и правее Робота. (Путь из корня в лист может проходить через вершину с Роботом, сворачивать влево, не доходя до нее и сворачивать вправо, не доходя до нее.) Через (ОЛ) обозначим условие "обработаны все листья левее Робота", а через (ОЛН) - условие "обработаны все листья левее и над Роботом". Нам понадобится такая процедура: procedure вверх_до_упора_и_обработать {дано: (ОЛ), надо: (ОЛН)} begin {инвариант: ОЛ} while есть_сверху do begin вверх_налево end {ОЛ, Робот в листе} обработать; {ОЛН} end; Основной алгоритм: дано: Робот в корне, листья не обработаны надо: Робот в корне, листья обработаны {ОЛ} вверх_до_упора_и_обработать {инвариант: ОЛН} while есть_снизу do begin if есть_справа then begin {ОЛН, есть справа} вправо; {ОЛ} вверх_до_упора_и_обработать; end else begin {ОЛН, не есть_справа, есть_снизу} вниз; end; end; {ОЛН, Робот в корне => все листья обработаны} Осталось воспользоваться следующими свойствами команд Робота (сверху записаны условия, в которых выполняется команда, снизу - утверждения о результате ее выполнения): (1) {ОЛ, не есть_сверху} обработать {ОЛН} (2) {ОЛ} вверх_налево {ОЛ} (3) {есть_справа, ОЛН} вправо {ОЛ} (4) {не есть_справа, ОЛН} вниз{ОЛН} Теперь решим задачу об обходе дерева, если мы хотим, чтобы обрабатывались все вершины (не только листья). Решение. Пусть x - некоторая вершина. Тогда любая вершина y относится к одной из четырех категорий. Рассмотрим путь из корня в y. Он может: а) быть частью пути из корня в x (y ниже x); б) свернуть налево с пути в x (y левее x); в) пройти через x (y над x); г) свернуть направо с пути в x (y правее x); В частности, сама вершина x относится к категории в). Условия теперь будут такими: (ОНЛ) обработаны все вершины ниже и левее; (ОНЛН) обработаны все вершины ниже, левее и над. Вот как будет выглядеть программа: procedure вверх_до_упора_и_обработать {дано: (ОНЛ), надо: (ОНЛН)} begin {инвариант: ОНЛ} while есть_сверху do begin обработать вверх_налево end {ОНЛ, Робот в листе} обработать; {ОНЛН} end; Основной алгоритм: дано: Робот в корне, ничего не обработано надо: Робот в корне, все вершины обработаны {ОНЛ} вверх_до_упора_и_обработать {инвариант: ОНЛН} while есть_снизу do begin if есть_справа then begin {ОНЛН, есть справа} вправо; {ОНЛ} вверх_до_упора_и_обработать; end else begin {ОЛН, не есть_справа, есть_снизу} вниз; end; end; {ОНЛН, Робот в корне => все вершины обработаны} Приведенная только что программа обрабатывает вершину до того, как обработан любой из ее потомков. Теперь изменим ее, чтобы каждая вершина, не являющаяся листом, обрабатывалась дважды: один раз до, а другой раз после всех своих потомков. Листья по-прежнему обрабатываются по разу: Под "обработано ниже и левее" будем понимать "ниже обработано по разу, слева обработано полностью (листья по разу, остальные по два)". Под "обработано ниже, левее и над" будем понимать "ниже обработано по разу, левее и над - полностью". Программа будет такой: procedure вверх_до_упора_и_обработать {дано: (ОНЛ), надо: (ОНЛН)} begin {инвариант: ОНЛ} while есть_сверху do begin обработать вверх_налево end {ОНЛ, Робот в листе} обработать; {ОНЛН} end; Основной алгоритм: дано: Робот в корне, ничего не обработано надо: Робот в корне, все вершины обработаны {ОНЛ} вверх_до_упора_и_обработать {инвариант: ОНЛН} while есть_снизу do begin if есть_справа then begin {ОНЛН, есть справа} вправо; {ОНЛ} вверх_до_упора_и_обработать; end else begin {ОЛН, не есть_справа, есть_снизу} вниз; обработать; end; end; {ОНЛН, Робот в корне => все вершины обработаны полностью} Доказательство правильности алгоритма. Докажем, что приведенная программа завершает работу (на любом конечном дереве). Доказательство. Процедура вверх_налево завершает работу (высота Робота не может увеличиваться бесконечно). Если программа работает бесконечно, то, поскольку листья не обрабатываются повторно, начиная с некоторого момента ни один лист не обрабатывается. А это возможно, только если Робот все время спускается вниз. Противоречие. Блок-схема алгоритма.

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Описание переменных и программа. Теперь реализуем операции с деревом позиций. Позицию будем представлять с помощью переменной k: 0..n (число ферзей) и массива c: array [1..n] of 1..n (c [i] - координаты ферзя на i-ой горизонтали; при i > k значение c [i] роли не играет). Предполагается, что все позиции допустимы (если убрать верхнего ферзя, остальные не бьют друг друга). program queens; const n = ...; var k: 0..n; c: array [1..n] of 1..n; procedure begin_work; {начать работу} begin k := 0; end; function danger: boolean; {верхний ферзь под боем} var b: boolean; i: integer; begin if k <= 1 then begin danger := false; end else begin b := false; i := 1; {b <=> верхний ферзь под боем ферзей с номерами < i} while i <> k do begin b := b or (c[i]=c[k]) {вертикаль} or (abs(c[i]-c[k])=abs(i-k)); {диагональ} i := i+ 1; end; danger := b; end; end; function is_up: boolean {есть_сверху} begin is_up := (k < n) and not danger; end; function is_right: boolean {есть_справа} begin is_right := (k > 0) and (c[k] < n); end; {возможна ошибка: при k=0 не определено c[k]} function is_down: boolean {есть_снизу} begin is_up := (k > 0); end; procedure up; {вверх_налево} begin {k < n} k := k + 1; c [k] := 1; end; procedure right; {вправо} begin {k > 0, c[k] < n} c [k] := c [k] + 1; end; procedure down; {вниз} begin {k > 0} k := k - 1; end; procedure work; {обработать} var i: integer; begin if (k = n) and not danger then begin for i := 1 to n do begin write ('<', i, ',' , c[i], '> '); end; writeln; end; end; procedure UW; {вверх_до_упора_и_обработать} begin while is_up do begin up; end work; end; begin begin_work; UW; while is_down do begin if is_right then begin right; UW; end else begin down; end; end; end. Расчёт вычислительной сложности. Емкостная сложность: В программе используется одномерный массив размерности n, поэтому объём входа и объём выхода совпадают и равны n. Количество пременных равно 3(i,b,k) + 1(const n), т.е. объём промежуточных данных равен 4. С(n)=n+4 Временная сложность:

Если рассматривать обработку каждого листа, без проверки на пути к нему, то временная сложность T(n) = n0+n1+n2+n3 +.+nn .

Но в случае, когда каждая вершина проверяется, временная сложность T(n) = o(n0+n1+n2+n3 +.+nn). И это тем вернее, чем больше n. Данный вывод получен на основе приведённых ниже статистических данных:

1234567
Общее кол-во листьев2740341390655987960800
Кол-во вершин построенного дерева.2341754153552
Время построения(сек)<0.01<0.01<0.01<0.01<0.01<0.01<0.01
8910111213
Общее кол-во листьев

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Курсовая: Нахождение всех комбинаций расстановки n ферзей на доске n X n

Кол-во вершин построенного дерева.20578394355391669268561894674890
Время построения(сек)<0.010.211.206.4837.12231.29
Тестирование. Построенная по описанному алгоритму программа при различных n выдаёт следующие данные: n=4 <1,2><2,4><3,1><4,3> <1,3><2,1><3,4><4,2> Т.е. количество расстановок равно 2. Ниже приведена таблица зависимости от n количества решений (R).
n =12345678910111213
R=1002104409235272426801420073712
Cписок литературы. 1) Кузнецов О.П. Адельсон-Вельский Г.М. Дискретная математика для инженера. – М.: Энергоатомиздат, 1988. 2) Евстигнеев В.А. Применение теории графов в программировании. – М.:Наука, 1984. 3) Основной алгоритм находился на BBS “Master of Univercity” в файле shen.rar в файловой области “Bardak” (тел. 43-27-03; время работы 21.00 – 7.00; FTN адрес – 2:5090/58).

© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.