Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Искусство поиска решения в нестандартной задаче

Покупка
Артикул: 487692.02.99
Доступ онлайн
239 ₽
В корзину
Книга является заключительной в авторской трилогии книг после «Современное программирование с нуля» и «Искусство алгоритмизации». Эта книга о том, что делать с задачей, если её решение нельзя вычитать в учебнике. Иначе говоря, — эта книга о творчестве в программировании. В тексте вы не найдете готовых рецептов, скорее, это описание того, как искать путь в интеллектуальной неизвестности, как выстроить свое мышление, так чтобы, не зная готовых формул и теорем, все же получить достаточно приличное решение за оптимальное время. Издание предназначено для широкого круга начинающих программистов — школьников, студентов, а также всех думающих разработчиков программного обеспечения.
Потопахин, В. В. Искусство поиска решения в нестандартной задаче : практическое руководство / В. В. Потопахин. - 2-е изд. - Москва : ДМК Пресс, 2023. - 167 с. - ISBN 978-5-89818-565-7. - Текст : электронный. - URL: https://znanium.com/catalog/product/2107920 (дата обращения: 07.05.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Москва, 2023

Потопахин В. В.

Искусство 
поиска решения 
в нестандартной 
задаче

2-е издание, электронное
УДК 004.421
ББК 32.973.26-018
П64

П64
Потопахин, Виталий Валерьевич.
Искусство поиска решения в нестандартной задаче / В. В. Потопа-
хин. — 2-е изд., эл. — 1 файл pdf : 167 с. — Москва : ДМК Пресс, 2023. — Систем. 
требования: Adobe Reader XI либо Adobe Digital Editions 4.5 ; 
экран 10". — Текст : электронный.
ISBN 978-5-89818-565-7

Книга является заключительной в авторской трилогии книг после «Современное 
программирование с нуля» и «Искусство алгоритмизации».
Эта книга о том, что делать с задачей, если её решение нельзя вычитать в учебнике. 
Иначе говоря, — эта книга о творчестве в программировании. В тексте вы не найдете 
готовых рецептов, скорее, это описание того, как искать путь в интеллектуальной неизвестности, 
как выстроить свое мышление, так чтобы, не зная готовых формул и 
теорем, все же получить достаточно приличное решение за оптимальное время.
Издание предназначено для широкого круга начинающих программистов — 
школьников, студентов, а также всех думающих разработчиков программного обеспечения.


УДК 004.421 
ББК 32.973.26-018

Электронное издание на основе печатного издания: Искусство поиска решения в нестандартной 
задаче / В. В. Потопахин. — Москва : ДМК Пресс, 2016. — 166 с. — ISBN 978-5-97060-198-
3. — Текст : непосредственный.

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

В соответствии со ст. 1299 и 1301 ГК РФ при устранении ограничений, установленных техническими средствами 
защиты авторских прав, правообладатель вправе требовать от нарушителя возмещения убытков или выплаты компенсации.


ISBN 978-5-89818-565-7
© Потопахин В. В., 2016 
© Оформление, издание, ДМК Пресс, 2016
ОГЛАВЛЕНИЕ

Введение ..........................................................5

ГЛАВА 1. Как решается сложная задача ..................7
Пошаговое уточнение неопределенностей ................................ 9
Формализация задачи ............................................................. 13
Решение как построение цикла Дейкстры ............................... 17
Цикл Дейкстры .............................................................................17
Алгоритмически конечная задача .................................................18
Интересный пример ................................................................ 19
Еще одно важное обстоятельство – запись алгоритма ............. 24
В заключение .......................................................................... 27

ГЛАВА 2. Полный перебор и его оптимизация ........ 28
Задачи, сводимые к перебору ................................................. 29
Проблема комбинаторного взрыва .......................................... 30
Главная мораль ........................................................................ 47

ГЛАВА 3. Как свести решение к задаче 
существования ................................................ 49
Главная идея ............................................................................ 49
Задача поиска квадратного корня ................................................50
Поиск отсутствующего числа ........................................................52
Решение уравнения Диофанта .....................................................58

ГЛАВА 4. Тождественные преобразования 
условий .......................................................... 64
Прежде всего необходимо убрать мусор из текста условия ..... 64
Что делать после генеральной уборки ..................................... 67
Задача о рекурсивной процедуре ............................................ 67
Задача о бесконечном слове ................................................... 69
Неопределенные уравнения .................................................... 71
Расчет оптимального плана производства ............................... 73
Математическая модель задачи ...................................................74
Оглавление

Способ расчета выручки ...............................................................74
Итак, где здесь геометрия? ..........................................................75
Задача. Раскладывание колечек по штырькам ......................... 77

ГЛАВА 5. Моделирование физических процессов .... 86
Модель движения системы тел в гравитационном поле ........... 86
Задача о сложении прямого и отраженного колебаний ............ 93
Задача о колебательном движении пружины ........................... 97

ГЛАВА 6. Несколько интересных задач ............... 100
Задача Дейкстры ................................................................... 101
Задача о поиске пути с наибольшим весом ............................ 108
Задача о минимальном количестве заправок ........................ 113
Задача. Постфиксная и префиксная записи 
арифметического выражения ................................................ 120
Прямая задача............................................................................120
Обратная задача ........................................................................123
Задача. Самый длинный путь рубки ....................................... 125
Задача. Одинокий путник с плохой памятью .......................... 131
Задача. Закраска односвязного контура ................................ 141
Обсудим некоторые алгоритмические идеи ...............................142
Задача. Живая группа Го ........................................................ 152
Задача о черных пятнах на белой шкуре ................................ 156
В заключение ........................................................................ 157

ГЛАВА 7. Практикум ........................................ 158
ВВЕДЕНИЕ

Книга, введение к которой вы сейчас читаете, третья в моем авторском 
курсе. Две первые – «Современное программирование с нуля» и 
«Искусство алгоритмизации» – посвящены вхождению в творчество 
и науку программирования. Книга «Поиск решения» должна познакомить 
вас с одним из возможных ответов на вопрос «Что делать с 
нетривиальной задачей, если её решение нельзя прочитать в хорошей 
книжке?».
Сразу обращаю ваше внимание на одно важное обстоятельство. 
Программирование можно понимать как технологию сборки решения 
из более мелких задач. Такой подход создал индустрию программирования. 
И программирование можно понимать как искусство поиска 
решения логически сложной задачи, сведение которой к более простым 
не решает проблемы, потому как она либо просто не разбивается 
на хорошие задачи, либо эти более простые все равно представляют 
собой систему, связанную сложной логикой. Технологическому подходу 
будет посвящена четвертая книга моего курса. А сейчас мы постараемся 
посмотреть на программирование как на интеллектуальное 
искусство.
Главная идея книги – показать процесс мыслительной деятельности 
таким, какой он есть на самом деле, с ошибками, тупиковыми 
вариантами, рождением красивой идеи. И что, пожалуй, главное – показать 
возможность такой организации мышления, при которой поиск 
решения становится системной и плановой работой. Конечно, по 
прочтении книги у вас не будет рецепта построения решения. Единственный 
метод борьбы с творческими проблемами – развитый мыслительный 
аппарат, поэтому все главы книги – это описание процесса 
поиска решения реальных задач. И поиск этот не бессистемный, путь 
к решению в каждой задаче лежит не только через интуитивные прорывы 
и даже не столько через них, сколько через анализ накопленной 
информации.
Основной метод, действие которого проявляется на каждом 
шагу, – это метод борьбы с неопределенностями. Решение каждой за-
Введение

дачи представляется как последовательность вопросов «Что нам еще 
не ясно?» и «Как с этим бороться?». Возможно, некоторые из использованных 
задач искушенному «решателю» покажутся простыми, но 
цель максимально осложнить чтение не ставилась, поэтому задачи 
разноуровневые и поэтому книга может оказаться полезной для людей 
с самой различной степенью подготовки.
Базовый язык книги – Компонентный Паскаль, современная версия 
хорошо зарекомендовавшего себя языка, но некоторые решения 
записаны на псевдокоде. В принципе, базовый язык мог бы быть и 
другим, но все же Паскаль представляется наиболее удачным средством 
организации простого и в то же время достаточно строгого описания. 
Мой программисткий и главным образом преподавательский, 
учительский опыт говорит, что императивный стиль письма более 
соответствует природе программисткого мышления, чем функциональный 
или другие. Впрочем, даже если читатель не особенно 
приветствует императивные языки или язык Паскаль, то и такой читатель 
проблем с прочтением книги не испытает. Я уверен, что языковые 
особенности для большинства задач нашей предметной области 
не должны играть существенной роли. 

P.S.
Обратите внимание на правила, выведенные в процессе решения, 
их немного, и они не составляют какой-либо завершенной теории. 
Создать систему правил можно, но это опасное занятие. Завершенная 
теория, скорее всего, привела бы не столько к повышению эффективности 
мыслительного процесса, сколько к ограничению ваших творческих 
возможностей. Поэтому правила, сформулированные во всех 
последующих главах, не носят характера предписаний, это скорее небольшие 
советы, корректирующие направление мышления.
ГЛАВА 1. 

Как решается 
сложная задача

Существует один общий подход к поиску решения сложной задачи, 
независимо от того, из какой она области: математики, физики или 
программирования. Выражается он в трех простых предложениях:
1. Определим тип задачи.
2. Вспомним, какими методами нам или кому-нибудь другому 
доводилось решать задачи такого типа.
3. Попробуем применить эти методы к поставленной задаче.
Подход кажется логичным и разумным. Ведь большинство задач, с 
которыми мы сталкиваемся, кем-то уже решены, кто-то уже знает, как 
ответить на заинтересовавший вопрос, ответ уже есть в совокупной 
базе знаний человечества. Но накопленное общечеловеческое знание – 
это достаточно сложная штука. Оно не так доступно, как хотелось 
бы в силу своей огромности. Существуют и другие причины, по 
которым конкретный человек, сталкиваясь с реальной задачей, может 
не найти готового решения. Поэтому, несмотря на то что человечество 
в целом знает и умеет довольно много, отдельный человек часто 
встречается с ситуацией неопределенной и, следовательно, творческой. 
А в такой ситуации наш алгоритм из трех предложений уже не 
работает. 
Кроме того, если взять действительно интересную задачу, то окажется, 
что определить, к какому типу она относится, довольно сложно. 
И часто задача будет относиться не к одному типу, а к нескольким. 
Например, это может быть задача комбинаторного характера с 
применением графов, или это может быть задача моделирования физических 
процессов с использованием графики и методов численной 
математики и т. д.

Если бы была возможна исчерпывающая классификация задач, с конечным 
количеством классов, четко отделимых друг от друга, то это бы 
Глава 1. Как решается сложная задача

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

Вроде бы нет ничего страшного, просто в таких задачах мы имеем 
дело со сложными типами, и все равно можно действовать по той же 
схеме, то есть последовательно выполнять действия 1, 2, 3.
К сожалению, не получается. Во-первых, сложных типов можно 
сконструировать огромное количество, а чем типизация обширнее, 
тем сложнее выполнять пункт первый. Во-вторых, чем больше типов, 
тем сложнее в них ориентироваться, а в-третьих, тем сложнее 
отличить, где заканчивается один и начинается другой. Например, 
задача графического моделирования физического процесса, – это 
задача численной математики, физики или это графическая задача? 
В общем, при попытке составить какую-то классификацию мы столкнемся 
с таким количеством проблем, что невольно придет мысль поискать 
другой подход.
Попробуем подойти к сложным задачам с другой стороны. Начнем 
с небольшого, но очень важного замечания. Что бы мы не изобретали, 
все упирается в рождение идеи. А идея всегда рождается интуитивно, 
причем независимо от степени её гениальности и значимости. Происходит 
это так: вы некоторое время сосредоточенно размышляете на 
заданную тему, и вдруг приходит решение, причем не совсем понятно, 
откуда. Это называется интуицией. Существуют различные теории, 
объясняющие интуицию, откуда она берется, что она такое сама по 
себе, но для нас эти теории ровным счетом ничего не значат, так как 
не дают метода мышления.
Все серьезные идеи рождаются интуитивно, что огорчает, так как 
совершенно не ясно, как интуицией управлять, но, с другой стороны, 
совершенно не подготовленный человек вряд ли сможет сформулировать 
красивую идею, что вселяет надежду. Ведь если для рождения эффективной 
идеи нужна подготовка, то, значит, интуиция где-то в своей 
основе содержит систему, какой-то метод, а методу можно научиться.
Что такой метод может из себя представлять? Можно ли описать 
его точно? Конечно, нельзя ожидать, что общий метод решения творческих 
задач будет иметь алгоритмическую ясность. Невозможно 
себе представить, что такой метод будет описанием последовательности 
действий. Хотя, конечно, многие люди, когда речь идет о методе, 
представляют некую последовательность инструкций, выполнив 
которые, можно получить верный результат. Но это глубокая, принципиальная 
ошибка.
Пошаговое уточнение неопределенностей

Поэтому мы сразу и навсегда откажемся от идеи разработать такой 
всеобъемлющий алгоритм. Кроме того, мы решительно откажемся от 
попыток до конца понять тайну творчества. Это слишком невероятно, 
чтобы интуиция, творческий инсайт подлежал исчерпывающему 
логическому анализу. Это то, чего мы не будем делать. А попробуем  
разработать подход, помогающий удержать направление исследования 
и превращающий хаос творчества в осмысленный процесс.
Итак, мы ищем не методы решения задач, а методы организации 
мыслительной деятельности. Такова наша цель. И, чтобы её достичь, 
не будем строить теорию, а получим умения из практики. Решая задачи 
и отмечая то, что помогло получить решение, как-то обобщать свои 
наблюдения и, если получится, выводить общие правила.

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

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

Пошаговое уточнение 
неопределенностей

Рассмотрим пример несложной задачи. Пусть требуется разработать 
алгоритм расчета всех простых чисел, не превосходящих заданное 
число N. Если для решения не требуется особой эффективности, например 
верхняя граница не слишком велика, то можно воспользоваться 
самой очевидной идеей: алгоритм решения – это цикл, в теле 
которого для каждого очередного числа выясняется, простое оно или 
нет, и если простое, то число печатается как результат.
Для того чтобы принять решение относительно простоты очередного 
числа, необходимо проверить все числа, могущие быть его делителями, 
и если хотя бы один делитель есть, то проверяемое очередное 
не простое, иначе все-таки простое.
Глава 1. Как решается сложная задача

Идея вполне понятна, но все же вчитаемся в текст более внимательно, 
все ли здесь действительно хорошо. Один неясный пункт 
есть, это фраза, требующая проверить все числа, могущие быть делителями. 
Я из своего личного преподавательского опыта знаю, что ученики, 
недостаточно искушенные в задачах математической природы, 
о такие вещи спотыкаются довольно часто. «Как проверить?» – это и 
есть уточняющий вопрос, ответив на который, мы сможем записать 
решение в завершенной форме.

Заметим, что любое исследование начинается с искусства вопроса. Правильно 
заданный вопрос – это, образно говоря, половина ответа.

Рассмотрим более сложный пример. Есть группа людей со вполне 
определенными симпатиями и антипатиями друг к другу. Необходимо 
расставить их по рабочим позициям так, чтобы коллектив 
оказался психологически наиболее устойчивым. Возможно, психология 
дает какие-то методы решения подобных задач, но мы психологической 
наукой не владеем. А из соображений здравого смысла 
ясно, что необходимо организовать перебор всех возможных вариантов 
и выбрать из них вариант с наибольшим значением критерия 
устойчивости. 
Это своего рода макроидея, или решение в первом приближении. 
Здесь сразу видны следующие неопределенности. Во-первых, что 
значит перебирать варианты? Ясно, что с людьми этого делать не 
получится, ни в одном языке программирования нет такого термина – «
люди». Эту неопределенность мы устраняем легко, пронумеровав 
группу. Тогда перебор вариантов расстановки людей сводится 
к перебору всех возможных перестановок их номеров. Кстати, появившийся 
термин «перестановка» наводит на мысль поискать какой-
нибудь уже известный алгоритм построения всех перестановок. Но 
здесь  возникает новая неопределенность. Совершенно не факт, что 
наше понимание термина перестановка совпадает с математическим 
пониманием. В этом надо убедиться.
Следующая неопределенность сложнее. Это критерий устойчивости. 
Ясно, что для каждой полученной перестановки необходимо 
что-то считать, и это что-то должно характеризовать устойчивость построенного 
коллектива. Мы должны определиться с математической 
формой этого критерия.    

Как известно, математика – это язык для точной записи знания, поэтому 
выше не зря появилось упоминание о математической форме записи кри-
Пошаговое уточнение неопределенностей

терия. Любая работа по устранению неопределенностей в конечном итоге 
должна привести к математически строгим формулировкам.

Таким образом, данная итерация мыслительного процесса должна 
нам дать формулу расчета критерия и алгоритм, генерирующий 
перестановки. В общем-то можно начинать писать код. Но на этапе 
разработки алгоритма есть еще одна фундаментальная неопределенность – 
это требование к скорости работы будущей программы или  
требование к скорости работы алгоритма. Конечно, скорость программы 
и скорость алгоритма – несколько разные вещи. Хороший алгоритм 
можно испортить плохой программой, а вот плохой алгоритм 
хорошей программой не исправишь, поэтому вопросы эффективности – 
это прежде всего вопросы алгоритмизации. 
В отношении поставленной задачи вопрос скорости очень актуален, 
мы пришли к необходимости использовать математическую 
конструкцию перестановок, а, как известно, для N элементов можно 
построить N! перестановок. Это очень большая величина, и если 
коллектив содержит более 10 человек, чисто переборный вариант 
решения нас вряд ли устроит, и есть смысл подумать о более быстром 
алгоритме, использующем какие-то особенности формулировки 
задачи, или обдумать возможность отказа от идеального решения. 
То есть следующая итерация борьбы с неопределенностью 
должна дать ответ на вопрос о желаемой эффективности алгоритма.


Таким образом, процесс поиска решения заключается в записи решения, 
так как оно уже понято, выявлении неопределенностей и формулировке 
вопросов, ответы на которые устранят неопределенности. И весь процесс 
можно разбить на ряд итераций, для каждой из которых выполняется очередная 
запись решения, выявляются очередные неопределенности, формулируются 
очередные вопросы.

Заметим, что метод ничего не говорит о том, как будет организован 
поиск ответов на поставленные вопросы, это уже несколько иная 
проб лема. Метод пошагового уточнения, – это общая форма организации 
мыслительного процесса, еще не гарантирующая успешности в 
частном деле поиска ответов на содержательные вопросы.
Важно заметить, что разбиение мыслительного процесса на фиксированные 
итерации довольно условно. Конкретная траектория поиска 
решения зависит от имеющейся системы знаний решателя, от 
степени развитости интуиции, от банальной удачи. Метод предлагает 
в общем-то простую вещь. Разбить процесс решения на этапы, в конце 
Глава 1. Как решается сложная задача

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

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

Набор проблем, – кстати, величина не постоянная. Появляющиеся 
идеи приближают окончательное решение не в арифметическом 
смысле, с каждым шагом, все теплее и теплее. Полученное промежуточное 
решение может поставить новую проблему. Например, в разобранном 
примере вывод о необходимости алгоритма построения 
перестановок ставит перед решателем сложнейшую проблему комбинаторного 
взрыва. 
Усложнение решения – процесс неизбежный. Необходимо понимать, 
что решатель, приступая к задаче, скорее всего, не до конца 
понимает её характер и природу. Процесс решения приводит к более 
точному пониманию, а следовательно, к проявлению проблем, которые 
существовали, но не были видны решателю.  
Еще одно важное замечание о порядке выбора подзадач. Предположим, 
что после очередной итерации мы имеем ряд проблем: А, В, 
С… и т. д. Какую из них выбрать для следующей итерации? Простая 
логика говорит, что ключевую, то есть такую, которая укажет магистральный 
путь для решения всей задачи. Наверное, это справедливо. 
Вопрос только в том, что, не решив задачу, нельзя сказать, какая 
проблема была главной, хотя опыт говорит, что интуитивно это 
как раз почти всегда ясно – ключевая проблема выглядит наиболее 
сложно.
Однако в этом вопросе есть важный психологический нюанс. Для 
успешной работы в задачу нужно погрузиться. Погружение, особенно 
для не вполне опытного исследователя, подразумевает хотя бы 
небольшой, локальный, но успех. Теперь представьте себе ситуацию. 
Вы приступаете к задаче и четко видите, что нужен ответ на сложный 
вопрос А и относительно простой вопрос В. Вы не сомневаетесь, что 
ответ на вопрос А будет ключом к решению, ответ на вопрос В имеет 
чисто технический характер. Простая логика говорит, что необходимо 
заняться вопросом А. Но, быть может, лучше решить технический 
вопрос В?! Вполне возможно, что его решение не очень важно, может 
быть, даже позже, получив ответ на вопрос А, вы поймете, что ответ на 
Доступ онлайн
239 ₽
В корзину