Может кто подскажет как сделать полный перебор элементов матрицы...
Допустим, дана матрица 10х10 и нужно перебрать все варианты размещения 4 элементов...
1-2-3-4, 1-2-3-5, 1-2-3-6... 3-5-6-9...
Естественно, процедурка (функция), должна работать с любым перебираемым множеством элементов и любым размером матрицы, пусть и очень долго... Лишь бы правильно и в полном объеме перебирала всё множество вариантов размещения...
Зараннее всем спасибо!!!
Advanced member
Статус: Не в сети Регистрация: 23.10.2003 Откуда: Иркутск/Майкоп
Наверное, проще всего с рекурсией. Процедуре передается число размещаемых элементов. Массив, в котором они размещаются, можно сделать глобальным. Дальше она перебирает все варианты, как можно поставить элемент на свободное место, и для каждого вызывает себя (уменьшив кол-во на 1).
_________________ Края каждого совершенно нового крышка процессора не на 100% гладкая. Это связано с тем, что следов мастерства не избежать. (c) Али.
Member
Статус: Не в сети Регистрация: 03.01.2004 Откуда: Питер
Перебор вариантов можно сделать так:
1. Все элементы массива нумеруем по порядку
1, 2, 3, ..., n
2. Переставляем 1-й элемент массива со 2-м, 3-м, ..., n-м
3. Переставляем 2-й элемент массива с 3-м, 4-м, ..., n-м
4. Переставляем 3-й элемент массива с 4-м, 5-м, ..., n-м
. . .
n-1. Переставляем (n-1)-й элемент массива с n-м
Вот такой алгоритм.
Реализуется он несложно, единственная проблема - что делать с результатами
( результаты - это, если не ошибаюсь, (n-1)! массивов ).
_________________ Здесь так мало тех, с кем легко говорить,
Еще меньше тех, с кем не страшно молчать (c)
Member
Статус: Не в сети Регистрация: 29.09.2004 Откуда: Курск
Спасибочки за отклики, но ужо мне подсказали... Без рекурсии, но довольно хитро...
Так вот на моём 850МГц Селероне, перебор всех вариантов размещения от 1 до 25 элементов в матрице, размером 25 (ну или 5х5), по времени идет 7 секунд, размером 30 - 228 сек., 35 - 7344 сек. и т.д. Причём с увеличением размерности и соотвественно количества проверяемых элементов на 1, время увеличивается РОВНО в 2 раза!!! Таким образом, перебор всех вариантов в матрице размером в 50 элементов займет 7,5 лет!!!!!!!!!! Прикольно... Это при том, что я думал над оптимизацией... Чуть ли не везде подставил register и т.д. Ну ладно... Прорвемси...
Member
Статус: Не в сети Регистрация: 15.04.2004 Откуда: Москва
Slava_rec 1. Какой компилятор?
2. Везде понаставил register? теперь убери. Не мешай компилятору.
3. Оптимизируй структуру хранения данных.
4. Ну в конце всего, перейди хотя бы на MMX
Да нет уж... Убирать register я не буду... Перебор 25 элементов стал занимать 6 сек (раньше 7), 26 - 12 (14), 27 - 24 (28)...
По поводу хранения данных, нечего оптимизировать... Все переменные служат для индексауции, кроме массива индексов элементов, собственно, варианта размещения (он каждый раз заполняется заново, а не дописывается в конец)...
Slava_rec Перебор, наверное, делаеться для каких-то целей! Так неужели нельзя на каком-то этапе отбрасывать "тупиковые ветки", которые для этой цели не подходят?
Процедура вот такая:
void GetAllVariants(register int NumberOfElements, register int MatrixSize)
{
DynamicArray<int> Variant;
Variant.Length = NumberOfElements; // Устанавливаем размер массива элементов варианта размещения равным количеству размещаемых элементов
register int i; // Индекс изменяемого элемента
register int Increase; // Число, на которое увеличиваются элементы
register int Modified = NumberOfElements - 1; // Индекс элемента, который изменялся последним
register int LastElement = NumberOfElements - 1; // Индекс последнего элемента
for (i = 0; i <= LastElement; i++)
Variant[i] = i; // Первый вариант размещения
Count++; // Счетчик вариантов
while (Modified >= 0) // Цикл выполняется до тех пор, пока последним изменяемым не будет первый элемент, а последний элемент при этом будет равен размеру матрицы
{
if (Variant[LastElement] == MatrixSize - 1) // Если последний элемент равен размеру матрицы,
Modified--; // то уменьшаем индекс элемента, который изменялся последним
else
Modified = LastElement; // иначе устанавливаем индекс этого элемента на последний элемент
if (Modified >= 0)
{
Increase = Variant[Modified] - Modified + 1; // Увеличение = Значение элемента с индексом последнего изменяемого - сам индекс последнего изменяемого + 1
for (i = LastElement; i >= Modified; i--) // Увеличиваем все элементы, после последнего изменяемого и сам изменяемый
Variant[i] = Increase + i; // Следующий вариант размещения
Count++;
}
}
}
Предполагается после вычисления очередного варианта, с ним проводить определенные действия, -> необходим КАЖДЫЙ вариант...
Добавлено спустя 2 минуты, 27 секунд: Матрица не обязательно квадратная... В данном алгоритме рассматривается сквозная нумерация элементов, начиная с нулевого... Переход к двумерным координатам осуществить просто...
Добавлено спустя 4 минуты, 5 секунд: Не понял на счет выравнивания на длину кэш-линии... Что есть это такое? А на счет размера массива, так int в самый раз по-моему...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения