Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.05.2017, 17:41   #1
K-Dot
Новичок
Джуниор
 
Регистрация: 14.05.2017
Сообщений: 3
По умолчанию Перебор разбиений

Привет.Есть задание,в котором сказано,что имеется группа людей и рост каждого из них.Необходимо разбить всех на 2 группы так,чтобы суммарный рост двух групп был наиболее близок.
Как начал решать эту задачу я:
количество всех разбиений,как я думаю,будет равным числу Стирлинга второго порядка,т.к. это разбиения без повторений.Далее необходимо перебрать все возможные разбиения на 2.Каким способом это можно реализовать?Находил в интернете возможность работы с битовой маской,однако,как мне кажется,это слишком сложно и проще будет другим методом.
K-Dot вне форума Ответить с цитированием
Старый 14.05.2017, 20:03   #2
K-Dot
Новичок
Джуниор
 
Регистрация: 14.05.2017
Сообщений: 3
По умолчанию

Думаю,что делать динамический двумерный массив для записи суммы каждого разбиения и элементов подмножеств будет затратно по памяти.Возможно стоит сделать один статический массив из 2-3 строк,где в 1 и 2 будут номера учеников входящих в 1 и 2 подмножества соответственно,а в 3 (хотя необязательно,можно рассчитать потом,при разборе предыдущих строк массива) разность сумм и/или рост каждого из 2х подмножеств.Если подскажите куда смотреть,чтобы понять,как перебирать все возможные разбиения,то буду очень благодарен.И правильно ли я понял,что нужно использовать числа Стирлинга 2го рода?Заранее спасибо!
K-Dot вне форума Ответить с цитированием
Старый 14.05.2017, 22:25   #3
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Да, мне тоже кажется, что число Стирлинга 2го рода подходит для определения количества разбиений. Только это никак не помогает, на мой взгляд, искать сами разбиения. Битовая маска подходит отлично. Пусть группа людей состоит из N человек. Тогда возьмем маску длины N - 1 и переберем значения маски от 0...01 до 1...1. i-й бит маски интерпретируем как номер группы i-ого человека. При этом считаем, что N-й человек всегда в нулевой группе, а счет начинаем не с нуля, чтобы в первой группе тоже всегда был хотя бы один человек.
Например:
N = 4
0001
0010
0011
0100
0101
0110
0111
Серым цветом отмечен N-й человек.
Если N достаточно мало (например, до 32), то можно использовать одну переменную типа int для хранения и перебора масок.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 15.05.2017, 00:30   #4
K-Dot
Новичок
Джуниор
 
Регистрация: 14.05.2017
Сообщений: 3
По умолчанию

Спасибо за ответ.
Цитата:
Сообщение от BDA Посмотреть сообщение
Например:
N = 4
0001
0010
0011
0100
0101
0110
0111
Т.е. при N=4 мы берем только 3 бита,серые,как я понял,это просто для того,чтобы показать и не относятся к битам?Если Вам не сложно,не могли бы вы расписать поподробнее (например при N=4).
K-Dot вне форума Ответить с цитированием
Старый 15.05.2017, 01:23   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Сначала я выписал все битовые маски при N=4 (получил 16 штук) и посмотрел на них. Во-первых, там было две маски 0000 и 1111, по которым получалась одна из групп пустая. Во-вторых, если рассмотреть произвольные две маски, например, 0110 и 1001 (одна, инверсия другой), то получится, что они задают одно и то же разбиение, ведь не важно, какая из групп первая, а какая вторая. Вот и получилось, что один бит закрепляется нулевым (считаем, что какой-то человек является главным в группе, то есть все люди делятся на тех, кто с ним, и кто не с ним). Тогда остается перебрать только значения для 3 битов, причем, дополнительно ограничить значения, чтобы вторая группа не получилась пустой. Вот и получается, что нужно перебрать все значения от 001 до 111. Если N<=33, тогда int хватит для хранения как раз 32битной маски (считаться будет долго). Вам остается только сделать цикл от 1 до ((1 << N) - 1) и на каждом шаге цикла считать сумму. Что именно вам тут непонятно? (т.е. я не очень понимаю, что расписать)
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Программа перебора вариантов (изменить перебор цифровой на перебор буквенный) BArt2000 Паскаль, Turbo Pascal, PascalABC.NET 5 02.03.2015 12:56
программа на Delphi7: требуется найти количество разбиений прямоугольника nxn "на плитки" Абдулгани Помощь студентам 7 25.04.2013 21:05
Перебор maxsept Общие вопросы Delphi 3 28.02.2013 19:03
найти оптимальное количество разбиений Надежда Ижбулатова Паскаль, Turbo Pascal, PascalABC.NET 1 26.04.2012 20:16
генерация всех разбиений целого числа Andrey344 Общие вопросы C/C++ 1 07.11.2011 21:20