Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Поиск элементов массива, чья сумма равна заданному числу

Ответить
Настройки темы
Поиск элементов массива, чья сумма равна заданному числу

Старожил


Сообщения: 155
Благодарности: 2


Конфигурация

Профиль | Отправить PM | Цитировать


Может кто знает, как реализовать такую штуку: есть массив чисел, необходимо найти такие элменты этого массива, чтобы сумма этих чисел равнялась определенному значению (либо установить, что такой комбинации элемнтов массива нет). Интересует алгоритм или какие-то общие соображения на эту тему. Я делаю так (для комбинации из, к примеру, 4 чисел): цикл по всем возможным комбинациям. Также еще один очень важный вопрос: это (см. код) действительно все возможные комбинации?

Код: Выделить весь код
int NUM[] = {10,20,30,40,50, <...>};
int COUNT = sizeof(NUM)/sizeof(int);
int SUM = 35;
int i,j,k,n;

<...>

for(i=0;i<COUNT;i++)
	for(j=0;j<COUNT;j++)
		for(k=0;k<COUNT;k++)
			for(n=0;n<COUNT;n++)
			{
				if((i!=j && i!=k && i!=n) && (j!=k && j!=n) && (k!=n))
				{
					if(NUM[i] + NUM[j] + NUM[k] + NUM[n] == SUM)
						printf("%d %d %d %d\n",i,j,k,n);
				}
			}

Отправлено: 00:18, 14-09-2006

 

редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Qwe1
Элементы положительные? Ограничение сверху на сумму есть? Если есть ограничение на сумму и элементы положительные, то можно применить динамическое программирование. Вариант с перебором всех комбинаций работает только при небольшом размере массива.

-------
http://ivank.ru


Отправлено: 01:37, 14-09-2006 | #2



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

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Gerdewski

Старожил


Сообщения: 260
Благодарности: 28

Профиль | Отправить PM | Цитировать


Каждый новый цикл нужно начинать с элемента, большего на 1 предыдущего.
т.е. не j=0 , а j=i+1 по-быстрее так заработает.
(наверное это имел ввиду ivank)
Складывать нужно обязательно 4 числа? А если сумма 3х, 2х или одно число равно заданному значению, как поступать тогда?

-------
Скажи точно. Сколько вешать в граммах?


Отправлено: 09:02, 14-09-2006 | #3


Старожил


Сообщения: 155
Благодарности: 2

Профиль | Отправить PM | Цитировать


ivank
1) Элементы все положительные;
2) "Определенное начение" (с которым идет сравнение) всегда меньше суммы всех элементов (примерно в 3 раза).

Gerdewski
1) У меня изначально (в цикле for) было так i=0, j=1, k=2, n=3, но потом я решил, что для полноты перебора необходимо проинициализировать именно нулями. Так ли это (?)
2) Аналогичные циклы у меня реализованы для 2, 3, ..., 7 переменных. Для 7 переменных, если не ошибаюсь, число комбинаций = число элементов в степени 7. Для 42 элементов имеем 230 539 333 248 комбинаций. На моем компе вычислялось почти 30 минут.

Знал бы, как прикреплять сюда файлы, выложил бы весь исходник


Отправлено: 09:31, 14-09-2006 | #4


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Qwe1
Так чему равна максимальная сумма? Приблизительно?

Если перебирать все комбинации, то это будет "цэ из эн по ка" операций, т.е. n!/(k!*(n-k!), где n - размер массива, k - число элементов в комбинации. Это выражение растёт очень быстро, а посему не подходит ни в одном практическом случае. Это я к тому, что перебор - не выход.

-------
http://ivank.ru


Отправлено: 10:31, 14-09-2006 | #5


Старожил


Сообщения: 155
Благодарности: 2

Профиль | Отправить PM | Цитировать


ivank
"цэ из эн по ка" - это, вроде, число сочетаний - количество способов выбрать K из N различных предметов. Вычисляется по следующей формуле: CNK = ANK/K! = N*(N-1)*...*(N-K+1)/K! = N!/(K!*(N-K)!). Так что, я не прав по поводу числа комбинаций (см. здесь).

Мне нужен хотя бы какой-нибудь способ. Я бы запустил алгоритм "в лоб" на каком-нибудь более-менее мощном компе и получил бы результат (здесь отрицательный результат - тоже результат). Поэтому хотелось бы этот алгоритм хоть как-нибудь соорудить. Если предложенный мною способ вычисления для 4 переменных верный, то я запулю еще для 8-ми переменных и поставлю на вычисление!! Хотя, если кто-то предложит более быстрый и т.д. код, буду рад

Отправлено: 11:00, 14-09-2006 | #6


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Qwe1
ВЫ упорно не отвечаете на мой вопрос. Какова максимальная сумма всех элементов? Каков максимальный размер массива? От этого зависит применимость того решения, которое есть у меня. Его асимптотическая сложность O(mn), где m - размер массива, n - максимальная сумма. Затраты памяти - O(n). Таким образом при отсутвии ограничения на максимальную сумму нам банально не хватит времени и памяти.

P.S. В предыдущем посте я наврал. На самом деле при "лобовом подходе" перебирать надо даже SUM(k=1, n, C_n_k). Т.е. сумма всех цэ из эн по ка для всех ка от 1 до эн. Это ещё хуже.

-------
http://ivank.ru


Отправлено: 11:30, 14-09-2006 | #7


Старожил


Сообщения: 155
Благодарности: 2

Профиль | Отправить PM | Цитировать


Вот реальный пример набора данных: 42 элемента, сумма = 1 233 188, значение для сравнения = 350 000. Сам массив:
int NUM[] = {
197900,70584,65006,39893,27638,
29448,17220,7750,39032,2870,
2010,22386,93275,20090,10906,
36162,4133,40180,64575,34440,
6027,8754,22960,4879,22960,
18311,39893,27638,58896,24108,
22386,2727,36162,4879,4133,
34440,5740,2727,15355,1665,
34440,8610};

Все остальные наборы примерно такие же. Их сумма и значение для сравнения - тоже примерно такого же порядка.

Отправлено: 12:02, 14-09-2006 | #8


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Ну тогда всё просто. (Если среда нормальная 32-битная и не проблема выделить 5 метров памяти).

Примерно так.
Код: Выделить весь код
int sum = 0;
int i, j;
for (i = 0; i < size; ++i)
    sum += NUM[i];

int *way = new int[sum+1];
for (i = 0; i < size; ++i)
    way = 0;

way[0] = 1;

for (i = 0; i < size; ++i)
    for (j = sum; j > 0; --j)
        if (j >= NUM[i] && way[j-NUM[i]] != 0)
            way[j] = NUM[i];

// n - требуемая сумма
if (!way[n])
    printf("Всё плохо\n");
else
{
    printf("Всё хорошо, путь:\n");
    for (i = n; i != 0; i -= way[i])
        printf("%d\n", way[i]);
}

delete[] way;
Не проверял, так как сейчас времени нет. Вечером может проверю. Но идея ясна, я надеюсь.

-------
http://ivank.ru


Последний раз редактировалось ivank, 14-09-2006 в 16:57.


Отправлено: 12:24, 14-09-2006 | #9


Старожил


Сообщения: 155
Благодарности: 2

Профиль | Отправить PM | Цитировать


ivank
Честно, мне не очень понятно
Всего 42 элемента. Надо найти такие, чья сумма равнялась 350 000. Теоритически их может быть и 2. Для предложенного набора - не 2 и не 3 точно. Может 6 или 7. А скорее всего - их вообще нет. Это и надо проверить!

Поэтому, если n - требуемая сумма (т.е. 350 000), то way[350000] ??

Отправлено: 12:48, 14-09-2006 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Поиск элементов массива, чья сумма равна заданному числу

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Удаление записей из таблицы по заданному времени на php magwolf Вебмастеру 5 14-08-2009 14:13
[решено] Чему равна скорость 1МБбит/сек ? Rock Хочу все знать 12 30-09-2008 04:50
GF8600gts Asus или др. чья лучше? Ochotnik Видеокарты 5 20-03-2008 19:12
С/С++ | Выбор 10 случайных элементов из массива Vovius Программирование и базы данных 5 29-08-2006 19:37
Решено | XML. DOM. Поиск дочерних элементов. penykov Программирование и базы данных 3 27-04-2006 15:46




 
Переход