`
Читать книги » Книги » Компьютеры и Интернет » Программирование » Жак Арсак - Программирование игр и головоломок

Жак Арсак - Программирование игр и головоломок

Перейти на страницу:

— если u истинно, то выполняется a, и все возобновляется.

Допустим, что условия t и u таковы, что я имею возможность проверить u, даже если проверка условия t дает значение ЛОЖЬ[29]. Тогда, пока условия t и u истинны, в цикле выполняется а.

Вот другая последовательность, которая может встретиться:

— проверяется условие t,

— если оно истинно, то проверяется u,

— если u ложно, то выполняется b, и все возобновляется.

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

ПОКА t ВЫПОЛНЯТЬ

  ПОКА t И u ВЫПОЛНЯТЬ а ВЕРНУТЬСЯ

  ПОКА t И НЕ u ВЫПОЛНЯТЬ b ВЕРНУТЬСЯ

ВЕРНУТЬСЯ

Мы перепишем программу для определения равнин, чтобы придать ей форму ПОКА, заключенного в скобки ЕСЛИ:

i := 1; р : = 0;

ПОКА in ВЫПОЛНЯТЬ

  ЕСЛИ a[i] = a[iр]

    ТО x := a[i]; р := р + 1; i := i + 1

    ИНАЧЕ i := i + 1

  КОНЕЦ_ЕСЛИ

ВЕРНУТЬСЯ

Мы обнаруживаем, что в нашем случае мы не можем объединить два условия с помощью операции И: если i не удовлетворяет условию, что i не больше n, то нельзя поставить вопрос относительно a[i]. Обрисуем трудность подходящим образом:

— нужно либо добавить в таблицу а поле, которое содержит какую-нибудь несущественную для нас величину (мы к этой величине не обращаемся);

— либо нужно допустить, что операция И не коммутативна. Для вычисления t и u мы вычисляем t, и если результат есть ЛОЖЬ, то все кончено и притом с результатом ЛОЖЬ. В противном случае результат есть значение условия u.

Тогда можно использовать наше преобразование:

i := 1; р := 0;

ПОКА in ВЫПОЛНЯТЬ

  ПОКА in И а[i] = a[iр] ВЫПОЛНЯТЬ

    x := а[i]; р := р + 1; i := i + 1

  ВЕРНУТЬСЯ

  ПОКА in И а[i] ≠ a[iр] ВЫПОЛНЯТЬ

    i : = i + 1

  ВЕРНУТЬСЯ

ВЕРНУТЬСЯ

Первый цикл движется по таблице а, пока обнаруживается, что элементы равны между собой. Более точно, р и i изменяются одинаково, так что разность iр остается постоянной. Все элементы a[i] сравниваются с одним и тем же элементом, и величина x остается постоянной, равной этому элементу, на протяжении всего цикла.

Второй цикл изменяет i до тех пор, пока не обнаружится пара элементов, отстоящих на р + 1.

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

a[j] = a[jр]

только пока jр остается на равнине, которую мы собираемся пройти. Наименьшее соответствующее i значение j удовлетворяет условию jр = i, или j = i + р.

Следовательно, можно увеличивать i от р в обоих циклах, не меняя действия программы, что ускоряет ее работу.

Чтобы ускорить и первый внутренний цикл, мы присвоим переменной x ее значение перед циклом и сохраним ее начальное значение в j. Так как iр остается постоянным, то можно вычислить значение р также и после выхода из цикла. Начальные значения суть i = j и р = р0, а конечные значения i и р удовлетворяют соотношениям iр = jр0, откуда р = i + р0 − j:

i := 1; р := 0

ПОКА in ВЫПОЛНЯТЬ

x := а[i]; j := i

  ПОКА in И а[i] = x ВЫПОЛНЯТЬ

    i := i + 1

  ВЕРНУТЬСЯ

  р := i + рj; i := i + p

  ПОКА in И а[i] ≠ a[iр] ВЫПОЛНЯТЬ

    i := i + 1

  ВЕРНУТЬСЯ

ВЕРНУТЬСЯ

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

Может быть, это связано с ходом мыслей, который я приобрел, преподавая[30].

Головоломка 35.

Хорошенько учтите то, что вы знаете: обозначим через и таблицу, которая дает последние элементы наилучших возрастающих последовательностей для (всех возможных) длин от 1 до m.

Покажем сначала, что ui < ui+1. Предположим, что это не так: пусть существует такая последовательность длины i + 1, у которой последний элемент не больше ui. Так как эта последовательность возрастает, то ее предпоследний элемент меньше ui+1 и потому меньше ui. Тогда, удаляя последний элемент этой последовательности, мы получили бы последовательность длины i с последним членом, меньшим ui, что противоречило бы предположению, что ui — последний элемент последовательности длины i с наименьшим возможным последним элементом.

Рассмотрим теперь следующий элемент x нашего вектора. Разместим его в упорядоченной таблице u. Может случиться, что x > um. Тогда элемент x можно присоединить к концу последовательности длины m; тем самым получилась бы (впервые) возрастающая последовательность длины m + 1, которая вследствие своей единственности была бы оптимальна.

Если x меньше u1, то им следует заменить для построения новой наилучшей последовательности с длиной 1. Если же, наконец, оказывается, что ui < x < ui+1, то x можно присоединить к концу последовательности с длиной i + 1, чтобы получить последовательность с длиной i + 1, которая лучше уже известной, и поэтому ui+1 следует заменить на х. Так как и упорядочена, то вы можете разместить в ней x с помощью дихотомического поиска.

Эта операция требует порядка log2 m действий для m, не превосходящих n. Так как вам требуется n обращений к таблице, то вы получаете верхнюю границу числа действий порядка n log2 n, что чрезмерно завышено.

Головоломка 36.

Предположим, что вы уже прошли первую цепочку вплоть до индекса i − 1 и получили наилучшие слова длины р, меняющейся от 1 до m. Вы рассматриваете символ в положении i и ищете его в другой цепочке. Его первое положение j1 может быть поставлено в конце некоторого слова — скажем, слова длины р1 — и даст слово длины р1 + 1, которое окажется лучшим, чем предыдущее: действительно, если j1 можно поставить после слова длины p1, то это значит, что его значение больше положения последнего символа в наилучшем слове длины р1, но меньше положения последнего символа в слове длины p1 + 1, Рассмотрим теперь второе появление того же символа во второй цепочке: j2 > j1. Его нельзя поставить в конце елова длины p1 + 1, хотя j2 и больше j1, потому что это — другое появление того же символа, и их не нужно смешивать. Поэтому достаточно ограничиться по поводу этого появления символа обращением к таблице в ее части от p1 + 2 до m.

Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Жак Арсак - Программирование игр и головоломок, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)