Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Посоветуйте пожалуйста алгоритм / 25 сообщений из 32, страница 1 из 2
17.02.2012, 12:28
    #37666918
_Case
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Добрый день!

Есть задача (проект на работе): N объектов нужно разбить на группы (объект может находиться только в одной группе), минимум в группе - 2 объекта. Нужно найти ВСЕ возможные разбиения на группы этих N штук объектов!

Алгоритм требуется детерминированный - то есть вероятностные методы (типа метода Монте-Карло и подобные), к сожалению не подходят..

Хотелось бы, если можно, какой-нибудь псевдо-код, неважно в каком виде (Pascal, C, C++, VB, C#, Java.. ) - или просто даже русскими псевдо-операторами.. Производительность роли не играет (то есть сколько угодно циклов в циклах)

Буду благодарен любому совету!

Заранее спасибо!
...
Рейтинг: 0 / 0
17.02.2012, 14:14
    #37667226
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,

Как вариант: для распределения - используйте круговой цикл.
Количество групп заранее неизвестно?
...
Рейтинг: 0 / 0
17.02.2012, 14:22
    #37667243
ПЕНСИОНЕРКА
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,

похоже теория вероятности

число сочетаний n(2)+n(3)+n(4)+n(5)+ .........kol=n!/(m!*(n-m)!)

при n=6 ~по~2=15
~~~~~~~~по~3=20

а если 6/4=15 да еще остаток из 2 позиций
непонятно, что вы хотите получить
...
Рейтинг: 0 / 0
17.02.2012, 14:24
    #37667248
kmaw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
...
Рейтинг: 0 / 0
17.02.2012, 14:25
    #37667252
kmaw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Сочетание из n элементов по m
...
Рейтинг: 0 / 0
17.02.2012, 15:48
    #37667450
_Case
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Usman,

Нет, количество групп заранее не известно
...
Рейтинг: 0 / 0
17.02.2012, 16:00
    #37667471
tevellius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,

Пусть A - исходный массив длины N. Выпишем его в форме вектора:

A = [a(1), ..., a(N)]

Для каждой группы запишем характеристический вектор X
-если элемент a(i) принадлежит группе, x(i) = 1, в противном случае - 0

например, для группы из элемента а(1) вектор будет иметь вид:
X({a(1)}) = [1,0,.....,0]
а X({a(1),a(2)}) = [1,1,0,....0]

Очевидно, что множество характеристических векторов взаимно-однозначно отображается на множество подмножеств исходного массива, и каждый X-вектор является записью двоичного числа разрядности N (N-битный байт, двоичное число с дописанными нулями впереди).

Количество X-векторов в точности равно 2^n (если включать нулевой вектор, соответствующий пустой группе) или 2^n-1 (если вырожденный случай с пустой группой выкидываем).

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

X-векторы легко отсортировать в естественном порядке (от 0 до 2^N-1)
[0,0,...,0] (=0)
[0,0,...,1] (=1)
....
[1,1,...,1] (=2^n-1)

Это дает общую идею алгоритма:

ДЛЯ счетчик = 3 ПО 2^N-1 С ШАГОМ 1 ЦИКЛ
ЕСЛИ СтепеньДвойки(счетчик) Тогда
ПРОДОЛЖИТЬ; //уходим на следующую итерацию
ИНАЧЕ
БитоваяМаска = ЧислоВБитовуюМаску(счетчик,N);
Группа = ВыбратьГруппу(ИсходныйМассив, БитоваяМаска)
КОНЕЦ ЕСЛИ;
КОНЕЦ ЦИКЛА;

Потребуется разработать функции:

СтепеньДвойки -возвращает булевский тип; Можно сначала вычислить массив степеней, и проверять попадает ли очередное значение счетчика в этот массив.

Либо просто считать количество единиц в битовой маске (если 1 - то это степень двойки).

ЧислоВБитовуюМаску - тут все очевидно, для примера ЧислоВБитовуюМаску(3,5) = 00101
ВыбратьГруппу - функция должна выбирать из исходного массива элементы, соответствующие 1 в битовой маске.

Цикл начинаем с 3, потому что 0...01 (=1) и 0...010 (=2), очевидно, не подходят по условию задачи.

Надо иметь в виду, что 2^10*n ~10^n, т.е. при N>30 количество всех возможных групп переваливает за миллиард.
...
Рейтинг: 0 / 0
17.02.2012, 16:01
    #37667473
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,

- M = N / 2 (количество групп)
- И комбинаторика (см. выше)
...
Рейтинг: 0 / 0
17.02.2012, 16:06
    #37667485
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Usman_Case,

- M = N / 2 (количество групп)
- И комбинаторика (см. выше)Поправочка:
M - Максимальное кол-во групп
...
Рейтинг: 0 / 0
17.02.2012, 16:14
    #37667496
tevellius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
UPD. Исправляю неверную оценку в конце предыдущего поста, 2^10*n ~ 10^3*n, множитель в степени 10 забыл :)
...
Рейтинг: 0 / 0
17.02.2012, 16:45
    #37667545
ПЕНСИОНЕРКА
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
ПЕНСИОНЕРКА_Case,

похоже теория вероятности

число сочетаний n(2)+n(3)+n(4)+n(5)+ .........kol=n!/(m!*(n-m)!)

при n=6 ~по~2=15
~~~~~~~~по~3=20

а если 6/4=15 да еще остаток из 2 позиций
непонятно, что вы хотите получить

вернее

n(2)+хвостик
или n(3)+....
или n(4)+.....
или n(5)
...
Рейтинг: 0 / 0
17.02.2012, 17:35
    #37667662
Abstraction
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
tevellius,

Вы перебираете упорядоченные разбиения.
Для неупорядоченных, ИМХО, проще рекурсивно развернуть: берём первый элемент, все остальные к нему добавляем или нет (2 k-1 -1), и объединяем со всеми разбиениями оставшегося множества, если их множество непусто.
...
Рейтинг: 0 / 0
17.02.2012, 18:23
    #37667742
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_CaseНужно найти ВСЕ возможные разбиения на группы этих N штук объектов
Первое, что очевидно, что количество этих групп не превышает int(N/2).
Второе, что не менее очевидно, придётся выполнять полный перебор (нам нужны разбиения, а не их количество).
Соответственно можем совершенно спокойно строить переборный алгоритм.
Первый этап - это организация внешнего цикла перебора количества групп. Очевидно и тривиально.
Второй, внутренний, этап - это генерация всех делений на заданное снаружи количество групп. Это не более не менее как создание заданного числа пустых групп, и затем рекурсивное (или псевдорекурсивное) присоединение очередного элемента к каждой из групп. С учётом ограничения "не менее 2 на группу" вводим 2 дополнительных ограничения в рекурсии - если количество нераспределённых элементов равно сумме количества групп с одним элементом и удвоенного количества пустых групп, прислединять можно только к этим группам, иначе к любым.
Ну собсно и всё...
...
Рейтинг: 0 / 0
17.02.2012, 19:36
    #37667852
kmaw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
ради любопытства, можно содержательную часть задачи привести?
...
Рейтинг: 0 / 0
17.02.2012, 19:49
    #37667870
_Case
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Akina_CaseНужно найти ВСЕ возможные разбиения на группы этих N штук объектов
Первое, что очевидно, что количество этих групп не превышает int(N/2).
Второе, что не менее очевидно, придётся выполнять полный перебор (нам нужны разбиения, а не их количество).
Соответственно можем совершенно спокойно строить переборный алгоритм.
Первый этап - это организация внешнего цикла перебора количества групп. Очевидно и тривиально.
Второй, внутренний, этап - это генерация всех делений на заданное снаружи количество групп. Это не более не менее как создание заданного числа пустых групп, и затем рекурсивное (или псевдорекурсивное) присоединение очередного элемента к каждой из групп. С учётом ограничения "не менее 2 на группу" вводим 2 дополнительных ограничения в рекурсии - если количество нераспределённых элементов равно сумме количества групп с одним элементом и удвоенного количества пустых групп, прислединять можно только к этим группам, иначе к любым.
Ну собсно и всё...

Акина, спасибо за ответ! Но, я наверно, не до конца привёл условие задачи - все объекты уникальные (у каждого свой ID), а Вы указали решение для набора из тождественных (неразличимых) элементов..

То есть группа из первого и второго элемента - это совершенно другая группа, чем например группа из предпоследнего и последнего..
...
Рейтинг: 0 / 0
17.02.2012, 20:05
    #37667896
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,

Используйте отображение
...
Рейтинг: 0 / 0
17.02.2012, 20:09
    #37667903
tevellius
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Abstraction,

упорядоченные подгруппы на самом деле не рассматриваются, но мой ответ вообще неправильный.

Я не до конца понял условие задачи :(

Приведенный алгоритм позволяет выделить все группы c числом элементов => 2 , а надо же найти все годные разбиения.

Действительно, на ум приходит рекурсия :)
...
Рейтинг: 0 / 0
17.02.2012, 20:41
    #37667934
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_CaseАкина, спасибо за ответ! Но, я наверно, не до конца привёл условие задачи - все объекты уникальные (у каждого свой ID), а Вы указали решение для набора из тождественных (неразличимых) элементов..

То есть группа из первого и второго элемента - это совершенно другая группа, чем например группа из предпоследнего и последнего..
Нет, это Вы ничего не поняли из того, что я написАл. Мой алгоритм предназначен как раз для уникальных элементов, и его надо дорабатывать, если имеются кратные элементы.
...
Рейтинг: 0 / 0
17.02.2012, 20:54
    #37667943
_Case
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Akina_CaseАкина, спасибо за ответ! Но, я наверно, не до конца привёл условие задачи - все объекты уникальные (у каждого свой ID), а Вы указали решение для набора из тождественных (неразличимых) элементов..

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

Да, да Вы правы, прощу прощения, я сначала неверно понял Ваш ответ, я спутал число групп с числом возможных разбиений на группы

Спасибо!
...
Рейтинг: 0 / 0
17.02.2012, 21:03
    #37667954
_Case
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
Usman_Case,

Используйте отображение

Вы имеете ввиду, "отбрасывание" симметричных групп при подсчете или какой-то конкретный существующий алгоритм ?
...
Рейтинг: 0 / 0
18.02.2012, 01:09
    #37668138
Aleksandr Sharahov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
(*
Найти количество разбиений на группы n объектов.
Объект может находиться только в одной группе.
Минимальная группа - 2 объекта.
--
Решение разложением по группам, содержащим первый объект
F(n)=Sum(C(n-1,k)*F(n-k-1),k=1..n-3), где:
k=1..n-3 - количество добавленных объектов в группу первого объекта,
C(n-1,k) - количество таких групп (первый и k выбранных),
F(n-k-1) - количество групп, содежащих остальные объекты.
*)

function F(n: integer): int64;
var
  k: integer;
  c: int64;
begin;
  if n<=1 then Result:=0
  else if n<=3 then Result:=1
  else begin;
    Result:=0;
    c:=1;
    for k:=1 to n-3 do begin;
      c:=c * (n-k) div k; //c(n-1,k)
      Result:=Result + c * F(n-k-1);
      end;
    end;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin;
  Memo1.Lines.Clear;
  for i:=1 to 26 do Memo1.Lines.Add(IntToStr(i)+' '+IntToStr(F(i)));
  end;
...
Рейтинг: 0 / 0
18.02.2012, 01:38
    #37668151
Aleksandr Sharahov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_Case,
а если надо, можно заменить вычисление биномиального коэффициента на вывод групп объектов.
...
Рейтинг: 0 / 0
18.02.2012, 04:03
    #37668227
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
_CaseUsmanВы имеете ввиду, "отбрасывание" симметричных групп при подсчете или какой-то конкретный существующий алгоритм ? Просто для унификации
...
Рейтинг: 0 / 0
18.02.2012, 13:09
    #37668370
Aleksandr Sharahov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
исправление
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
(*
Найти F(n) количество разбиений n различных объектов на группы не менее чем из двух объектов.
--
Решение разложением по группам, содержащим первый объект
F(n)=1+Sum(C(n-1,k)*F(n-k-1),k=1..n-3), где:
n>=2     - количество объектов,
k=1..n-3 - количество добавленных объектов в группу первого объекта,
C(n-1,k) - количество таких групп (первый и k выбранных),
F(n-k-1) - количество групп, содержащих остальные объекты.
*)

function F(n: integer): int64;
var
  k: integer;
  c: int64;
begin;
  if n<2 then Result:=0
  else begin;
    Result:=1;                         //группа, содержащая все объекты
    c:=1;
    for k:=1 to n-3 do begin;
      c:=c * (n-k) div k;              //c(n-1,k)
      Result:=Result + c * F(n-k-1);
      end;
    end;
  end;
...
Рейтинг: 0 / 0
18.02.2012, 13:45
    #37668397
Aleksandr Sharahov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте пожалуйста алгоритм
kmawради любопытства, можно содержательную часть задачи привести?

Количество способов разбить население на партии.
В каждой партии, как минимум, один начальник и один дурак.
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Посоветуйте пожалуйста алгоритм / 25 сообщений из 32, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]