Пусть дан вектор, образованный n целыми числами. Подпоследовательностью этого вектора называется набор элементов, в котором индексы идут подряд. Найти подпоследовательность с максимальной суммой. Если вы предпочитаете другую формулировку, то найдите индексы i, j, для которых величина

ai + ai+1 + … + aj−1 + aj

максимальна. Внимание: время вычисления не должно расти намного быстрее, чем n, когда n увеличивается…

Эта головоломка до некоторой степени напоминает головоломку о возрастающих подпоследовательностях, но она гораздо менее сложна. Подумайте: линейная зависимость от n! Да ведь это, грубо говоря, означает, что каждый элемент вектора рассматривается только один раз. Вам следует составить цикл

ДЛЯ i := 1 ШАГ 1 ДО n ВЫПОЛНЯТЬ … ВЕРНУТЬСЯ

И никаких циклов в этом цикле! В ответе вы получаете искомые индексы. Озадачивающе, не так ли? Я потерял на это немало времени. И тем не менее, какое простое решение!

Как вы находите?

<p>Часть II. Первая помощь</p>

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

Некоторые упражнения кажутся мне настолько очевидными, что я ничего про них не скажу. Но, конечно, это субъективная точка зрения: они могут не казаться очевидными вам. Может быть, потому, что вы не видите, в чем задача: разберите простые случаи вручную, В любом случае старайтесь сформулировать задачу с максимальной возможной полнотой, Если и после этого вы по- прежнему не видите, как вам ее охватить, поговорите с друзьями или с приятелями, Я умышленно не собираюсь сообщать вам все. Эта книга написана для того, чтобы вы стали программировать. Вам играть…

<p>1. Случайные числа</p>

Упражнение 2.

Нужно изучить поведение дробной части (x + a)8, когда x меняется от 0 до 1. Нарисуйте, хотя бы приближенно, кривую, представляющую эту функцию. Рассмотрите интервал на оси x, в котором значение функции меняется от некоторого целого числа до следующего за ним. Отметьте на кривой точку, в которой ордината равна этому целому, увеличенному на 0,5. Она разбивает область изменения x на два интервала. Равны ли между собой эти две половинки? Если одна из них больше другой — и если это одна и та же половинка для всех интервалов — то у вас больше шансов получать числа, меньшие (или большие, вам будет видно самим), чем 0,5.

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

дробная_часть ((x + a)8) = x,

иначе вы вместо случайной последовательности получите постоянную последовательность. Проверьте числа x = 0, x = 0,5 и x = 1.

Упражнение 4.

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

Почему не разделить интервал (0, 1) на 6 частей?

Или еще по-другому: почему бы не умножить выше случайное число на 6. Тогда оно окажется в интервале (0, 6), исключая 6. Если вы возьмете целую часть результата, то вы получите целое число от 0 до 5, включая границы, с равными вероятностями для каждого числа… Завершить следует вам, я уже сказал слишком много!

Игра 1.

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

Похожие книги