Главная » Просмотр файлов » В. Рубанцев - Как решать комбинаторные задачи на компьютере

В. Рубанцев - Как решать комбинаторные задачи на компьютере (1127108), страница 7

Файл №1127108 В. Рубанцев - Как решать комбинаторные задачи на компьютере (В. Рубанцев - Как решать комбинаторные задачи на компьютере) 7 страницаВ. Рубанцев - Как решать комбинаторные задачи на компьютере (1127108) страница 72019-05-11СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 7)

. .for (int i = 1; i <= nPart; ++i){int j = a[i];s += j.ToString();if (i != nPart) s += "+";}. . .}73Рис. 9.8. Красиво поделились!В книге Красиковых [КК07], на страницах 197-200 вы найдёте итерационную версию алгоритма, который генерирует все разбиения заданногочисла в антилексикографическом порядке, то есть как и у нас.

Он реализован на языке C++, так что можете сравнить его с нашим вариантом.Далее, на страницах 200-202 рассматривается алгоритм разбиения числана заданное количество частей.В книге [KS98], на страницах 67-68 представлен тот же самый рекурсивный алгоритм для генерации всех разбиений числа, что и в нашей программе. А дальше рассматриваются диаграммы Феррерса и алгоритмразбиения числа на заданное количество частей.Большие числа склонны давать огромное количество разбиений, а ведьиногда нам нужно просто узнать, сколько имеется тех или иных разбие-74ний, не генерируя их одно за другим.

В той же книге [KS98] на этот случайуже готов Алгоритм 3.5, который мы любезно позаимствуем для собственных нужд.В метод новой кнопки btnEnumPart Посчитать P(n,k)! мы записываем перевод алгоритма на Си-шарп:private void btnEnumPart_Click(object sender, EventArgs e){int n = (int)udNum.Value;adds = new int[n + 1];int k = (int)udK.Value;int[,] p = new int[n + 1, k + 1];enumPart(p, n, k);for (int i = 1; i <= n; ++i){string s = "";int pn=0;for (int j = 1; j <= k; ++j){pn += p[i, j];s += ("P("+i + "," + j + ")=" + p[i, j].ToString()+" ");}if (n==k)lstVar.Items.Add("P(" + i +") = " + pn);lstVar.Items.Add(s);}lstVar.Items.Add("");lstVar.TopIndex = lstVar.Items.Count - 22;}void enumPart(int[,] p, int n, int k){p[0, 0] = 1;for (int i = 1; i <= n; ++i)p[i, 0] = 0;for (int i = 1; ifor (int j = 1;{if (i < 2 *p[i, j]elsep[i, j]}<= n; ++i)j <= Math.Min(i,k); ++j)j)= p[i - 1, j - 1];= p[i - 1, j - 1] + p[i-j, j];}Теперь нам не составит никакого труда удовлетворить своё любопытствобез лишних подробностей (Рис.

9.9).75Рис. 9.9. Статистика знает всё!Давайте ещё более сконцентрируем наш алгоритм, чтобы он выдавалтолько общее количество разбиений для заданного числа n, то есть P(n).Добавляем кнопку btnEnumPart2 Посчитать P(n)! и переводим Алгоритм3.6:private void btnEnumPart2_Click(object sender, EventArgs e){int n = (int)udNum.Value;int[] p = new int[n + 1];enumPart2(p, n);for (int i = 1; i <= n; ++i){lstVar.Items.Add("P(" + i + ") = " + p[i]);}lstVar.Items.Add("");lstVar.TopIndex = lstVar.Items.Count - 22;76}void enumPart2(int[] p, int n){int sign = 0;int sum = 0;int w = 0;int w2 = 0;int j = 0;p[0] = 1;p[1] = 1;for (int i = 2; i <= n; ++i){sign = 1;sum = 0;w = 1;j = 1;w2 = w + j;while (w <= i){if (sign==1)sum += p[i-w];elsesum -= p[i-w];if (w2 <= i){if (sign == 1)sum += p[i - w2];elsesum -= p[i - w2];}w += (3*j+1);++j;w2 = w + j;sign = 0-sign;} //whilep[i] = sum;} //for}Тут нужно отметить, что авторы книги [KS98] запутались в алгоритме инапечатали странную таблицу 3.1, в которой посчитаны не все значенияP(m,n), поэтому P(m), начиная с m=11, неверные.В главе Даёшь сотню! нам понадобятся композиции числа 9.

Если в разбиениях порядок слагаемых значения не имеет (обычно они записываются встандартной форме, но это непринципиально), то в композициях важен ипорядок слагаемых в записи. Это значит, что для каждого разбиения мы77должны составить и все перестановки слагаемых. Если k=1, то число разбиений равно числу композиций и равно единице, то есть и разбиение, икомпозиция равны самому числу n.Если k=2, то возможны варианты разбиений.

Если n, к примеру, равняетсяпяти, то мы имеем два разбиения:4132А композиций вдвое больше, поскольку числа в разбиениях можно переставить:41и1432и23Для k=3 число композиций утраивается по сравнению с разбиениями:311221311и131и113221и212и122Дальше можно не продолжать…Таким образом, мы можем дополнить алгоритм для генерирования разбиений кодом для перестановки слагаемых, но лучше использовать болеепростой алгоритм, который оба действия выполняет одновременно.В книге Handbook of Applied Algorithms, на странице 12 приведён красивыйкороткий алгоритм на этот счёт. Одна беда – он не работает.Обратимся к книге Algorithms for Programmers: Ideas and Source Code, где вглаве 7 мы найдём «классное» решение нашей проблемы. Код несколькотяжеловат, но зато универсален: позволяет генерировать композиции невсе разом, а по числу групп, причём в прямом (лексикографическом) и обратном (антилексикографическом) порядке.Переводим код с языка C++ на C# и добавляем новый класс в нашу библиотеку:public class Compositions{int N;int K;int[] p;78int nk1; //= N-K+1//КОНСТРУКТОРpublic Compositions(int n, int k){N = n;K = k;nk1 = N - K + 1;//nk1 >= 1 !!!p = new int[K+1];first();}public void first(){p[0] = nk1;p[K] = 0;for (int i = 1; i < K; ++i)p[i] = 1;}public void last(){for (int i = 0; i < K; ++i)p[i] = 1;p[K-1] = nk1;}public int next(){int i = 0;//ищем первое слагаемое, большее 1:while (p[i] == 1) ++i;//текущая композиция - последняя:if (i == K) return K;int v = p[i];p[i] = 1;p[0] = v-1;++i;++p[i];return i;}public int prev(){int v = p[0];//текущая композиция - первая:if (v == nk1) return K;p[0] = 1;int i = 1;//ищем первое слагаемое, большее 1:while (p[i] == 1) ++i;--p[i];79p[i-1] = v+1;return i;}public int[] data(){return p;}}Устанавливаем кнопку btnComposition Композиции! и запускаем генераторна полную мощность:private void btnComposition_Click(object sender, EventArgs e){int n = (int)udNum.Value;int k = (int)udK.Value;if (n < k) MessageBox.Show("Число меньше слагаемых!", "Разбиения");//выводим в антилексикографическом порядке:bool rq = false;//выводим в лексикографическом порядке://bool rq = true;Compositions P = new Compositions(n, k);if (rq) P.last();else P.first();nVar = 0;//только считаем://if (rq)//do//{//++nVar;//} while (P.prev() != k);//else//do//{//++nVar;//} while (P.next() != k);//генерируем композиции:int[] p = P.data();int q = k - 1;do{++nVar;//печатаем композицию:string s = "";for (int i = 0; i < k; ++i){s += (p[i] + " ");}lstVar.Items.Add(s);80if (rq) q = P.prev();else q = P.next();} while (q != k);lstVar.Items.Add("Всего композиций " + nVar);lstVar.Items.Add("");lstVar.TopIndex = lstVar.Items.Count - 22;}Если вы раскомментируете строки после //только считаем:, то можете закомментировать генерирование композиций и получить только числокомпозиций.

Порядком вывода слагаемых управляет логическая переменная rq.Ну и для уравновешивания кнопок на форме поставим ещё одну btnComp100 Композиции 100!. В её метод клика впишем облегчённую версию алгоритма, который используется в последней главе:private void btnComp100_Click(object sender, EventArgs e){int n = (int)udNum.Value;int k = (int)udK.Value;if (n < k) MessageBox.Show("Число меньше слагаемых!", "Разбиения");nVar = 0;//массив с числами композиции:int[] c= new int[n + 1];//формируем начальную композицию:c[1] = n - k + 1;for (int j = 2; j <= k; ++j)c[j] = 1;//генерируем остальные композиции:writeC(c, k);compC(c, 1, k);lstVar.Items.Add("Всего композиций " + nVar);lstVar.Items.Add("");lstVar.TopIndex = lstVar.Items.Count - 22;}void compC(int[] a, int n, int nGr){//для первой композиции:if (nGr == 1) return;int[] L = (int[])a.Clone();while (L[n] > 1){--L[n];++L[n + 1];writeC(L, nGr);if (n + 1 < nGr){compC(L, n + 1, nGr);81}}}//ПЕЧАТАЕМ ОЧЕРЕДНУЮ КОМПОЗИЦИЮvoid writeC(int[] a, int n){++nVar;string s = "";for (int i = 1; i <= n; ++i)s += (a[i] + " ");lstVar.Items.Add(s);}Сравнительные испытания обоих алгоритмов показывают их полное согласие с комбинаторной теорией (Рис.

9.10).Рис. 9.10. Числовой композитор в действии!82Примерный вид интерфейса приложенияИсходный код программы находится в папке Разбиения.831. Как мы знаем, наборы монет (или других объектов) могут бытьразными, однако пользователи нашей программы лишены возможности задавать наборы, отличные от тех, что уже «зашиты» вкоде программы. Добавьте компонент TextBox, чтобы пользователимогли передавать в приложение собственные наборы монет.2.

В книге А.М. и И.М. Ягломов Неэлементарные задачи в элементарном изложении есть ряд задач по размену денег и разбиениючисел.Решите их помощью нашей программы и сравните затраты труда слогическими решениями авторов книги!19. Сколькими способами можно разменять 20 копеек на монетыдостоинством 5 копеек, 2 копейки и 1 копейка.20. Сколькими способами можно составить n копеек из монет достоинством 2 копейки и 1 копейка.21**.

Сколькими способами можно составить n копеек из монет:а) достоинством 1 копейка, 2 копейки и 3 копейки?б) достоинством 1 копейка, 2 копейки и 5 копеек?21**. Сколькими способами можно составить рубль из монет достоинством в 1, 2, 5, 10, 20 и 50 копеек?22. Сколькими способами можно представить число n в виде суммы двух целых положительных слагаемых, если представления,отличающиеся лишь порядком слагаемых, считать одинаковыми?Конечно, решение задач с неопределенной суммой в n копеек потребует и размышлений, а не только нажимания кнопки.3. Двойные кружкиРешите такую задачу (Рис.

9.15). Впишите в кружки, расположенныена окружности, 9 чисел, сумма которых равна 100. В те кружки, чтонаходятся снаружи, следует записывать те же числа, что и в соприкасающихся с ними кружках (то есть каждое число используется вожерелье дважды).84Теперь составьте из любых пар чисел натуральный ряд последовательных чисел максимальной длины, начинающийся с единицы.Например, при таком заполнении бусин числами мы получим ряд,очень близкий к рекордному (Рис.

9.16).Рис. 9.15. Двойное ожерельеРис. 9.16. Почти рекордный результатОн состоит из 37 чисел: 1, 2 (1+1), 3, 4, 5 (4+1), 6 (3 + 3), 7 (4 +3), 8 (4+4), 9, 10 (9 +1), …, 35 (18 + 17), 36 (18+18), 37 (22+15).85А самая длинная последовательность включает 40 чисел, причёмзадача имеет единственное решение (Рис. 9.17).Рис. 9.17. А вот и рекорд!Исходный код программы находится в папке Двойные кружки.86ОтветыСловесные магические квадраты87Литература[РВ13]Рубанцев ВалерийТотальный тренинг по Сишарпу. Большой практикум попрограммированию на языке C#RVGames, 2013.

– 615 с.[KS98]Kreher D.L., Stinson D.R.Combinatorial Algorithms: Generation, Enumeration, and SearchCRC, 1998.- 344 c.ISBN: 084933988X88[WM99]Weiss M.A.Data Structures and Problem Solving Using C++Pearson Education, 1999. – 976 с.ISBN 0321205006[ГМ72]Гарднер МартинМатематические досугиМ.:Мир, 1972. – 495 с.[ГМ90]Гарднер МартинПутешествие во времениМ.:Мир, 1990. – 341 с.ISBN: 5-03-001166-889[ГМ10]Гарднер Мартин1000 развивающих головоломок, математических загадок иребусов для детей и взрослыхACT, Астрель, 2010.

– 287 с.ISBN 978-5-17-059779-6ISBN 978-5-271-24093-5[КД43]Дональд Эрвин КнутИскусство программирования,том 4, выпуск 3. Генерация всехсочетаний и разбиений.Вильямc, 2007. – 208 с.ISBN: 978-5-8459-1132-2[КД44]Дональд Эрвин КнутИскусство программирования,том 4, выпуск 4.

Генерация всехдеревьев. История комбинаторной генерацииВильямc, 2007. – 160 с.ISBN: 978-5-8459-1158-290[КК07]Красиков И. В., Красикова И. Е.АлгоритмыЭксмо, 2007.- 256 с.ISBN: 978-5-699-21047-3Серия: Просто как дважды два[ЛВ88]Липский В.Комбинаторика для программистовМосква: Мир, 1988. – 200 с.91[МФ06]Меньшиков ФёдорОлимпиадные задачи по программированиюПитер, СПб, 2006.

– 315 с.ISBN: 5-469-00765-09293.

Характеристики

Тип файла
PDF-файл
Размер
9,17 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6487
Авторов
на СтудИзбе
303
Средний доход
с одного платного файла
Обучение Подробнее