Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/146: Рейтинг темы: голосов - 146, средняя оценка - 4.60
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49

Подбор чисел из массивов для получения нужной суммы

26.03.2014, 15:01. Показов 31871. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!!! Не могу придумать алгоритм для решения задачи:

Переформулировал задачу ибо нужна помощь в алгоритме а не написании кода.

Есть 2 массива каких то чисел в сумме дающих какую то сумму к примеру 1250 или 1500


Так вот задача на основе двух исходных массивов получить два массива чисел дающих 1000 и отдельно 250
Или 1000 и 500 к примеру.

При чем чтоб в обоих новых массивах содержались числа и из первого и из второго исходных массивов.

Очень нужна помощь=(
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.03.2014, 15:01
Ответы с готовыми решениями:

Подбор нужной суммы из заданных чисел С Повторением
Добрый день! Прошу помочь: ищу способ подобрать сумму из массива чисел с возможностью повторения данных чисел для получения нужной...

Memo поиск нужной суммы из нескольких чисел
Доброго времени товарищи! В проекте потребовалось реализовать такую штуку: К примеру в memo хранятся строки с целыми числами: 2 3 5...

Подсчет нужной суммы из выборки чисел в Excel 2007
Добрый день, дорогие форумчане! Помогите пожалуйста решить следующую проблему в Excel 2007: Имеется диапазон с разными числами...

18
26.03.2014, 17:04

Не по теме:

Всё же советую переписать задачу дословно, может Вы не правильно поняли задание. Хоть и похоже на правду

0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
26.03.2014, 17:14
thisiswhite, а если это сделать невозможно?
0
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
26.03.2014, 19:16  [ТС]
Это жутко плохо если не возможно! Ибо это важная часть моего дипломного.

Добавлено через 5 минут
Надо придумать реализацию любыми путями. Данный участок программы собирает в гриде все часы возложенные ранее на плечи одного преподавателя по двум формам ЗФО и ДФО и затем в отчете разбивает его часы по ставке и если ставка 1.25 или полоторы или 2 в отчете должны быть отдельно часы дающие целую ставку и часы дающие в сумме 0.25 ставки.

И это бы уже было воплащено в жизнь как минимум перебором. Если бы не одно НО!!! и 1 ставку и 0.25 должны попасть часы и из ЗФО и из ДФО.

Добавлено через 2 минуты
К слову не обязательно получать точно 1000 можно + - Погрешность допустима не большая.
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
26.03.2014, 20:02
Цитата Сообщение от thisiswhite Посмотреть сообщение
Это жутко плохо если не возможно! Ибо это важная часть моего дипломного.
Может сама задача не предусматривает получения таких данных.
Если совсем уж грубо,то можно поступить так:
1.Слили 2 массива в 1,отсортировали.
2.Нашли max элемент.
3.Из большей суммы вычли этот элемент.Если оставшееся меньше половины,ищем совпадение по этому элементу.Нашли.Задача решена.
4.Ищем следующий max и переходим к пункту 3.

И так далее либо до получения 0,либо до ухода в минус.
Если ушли в минус задача усложняется,надо перейти вверх на деление и поискать не максимальный а второй максимальный.
В худшем случае получим полный перебор.

ограничение с разными массивами сложнее,как вариант чередовать поиск по разным массивам.
1
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
26.03.2014, 22:26  [ТС]
Как вариант. Но надо ещё подумать может что придумаем оришенальнее.
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
26.03.2014, 22:39
thisiswhite, если придумаете - напишите,было бы любопытно взглянуть.
0
194 / 174 / 30
Регистрация: 10.07.2012
Сообщений: 800
27.03.2014, 21:10
Если ограничения на сумму небольшие, то решается дп. Довольно известная задача, должна гуглится.
0
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
27.03.2014, 22:37  [ТС]
Гуглилась бы уже бы нагуглили...
0
294 / 265 / 48
Регистрация: 09.04.2013
Сообщений: 1,038
28.03.2014, 01:24
Цитата Сообщение от thisiswhite Посмотреть сообщение
Если бы не одно НО!!! и 1 ставку и 0.25 должны попасть часы и из ЗФО и из ДФО.
А 1,25 ? 1,5 ? 2 ? В них тоже может попадать, или нет ?
Напоминает задачу о ранце , не знаю насколько она тут применима
Цитата Сообщение от salam Посмотреть сообщение
Довольно известная задача, должна гуглится.
Хорошо гуглится обычно то, название чего точно знаешь.
2
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
28.03.2014, 01:42  [ТС]
Да "о ранце" это основной пример подобной задачи. Но мой случай имеет жесткое усложнение.

Добавлено через 3 минуты
Пока что появились некие наработки (не сказать что мои, товарища) пока не известно на сколько рабочего алгоритма...
* есть 2 массива чисел. нужно получить 2 определенные суммы из этих чисел, обязательно из обоих массивов.
* для этого класс числа имеет свойство - к какому массиву он относится.
*
* алгоритм - рекурсивный перебор в ширину. то есть дерево с 1 вершиной.
*
* 1. берем первую сумму. создаем объекты чисел из обоих массивов. каждый объект будет представлять свой пусть вычислений.
* у каждого из объектов есть список всех исходных чисел - все числа из обих массивов, кроме самого себя.
* у каждого из объектов есть список использовавшихся чисел - оно само и его предки.
*
* 2. создаем объект. он удаляет себя из списка исходных чисел и добавляет себя в список использовавшихся.
* 3. вычитаем из суммы все числа из использовавшихся, получаем разницу. для каждого объекта будет своя разница.
* 4. если разница +- погрешность равна 0, то нужная последовательность чисел найдена, гоу 5.
* 5. мы ее проверяем, есть ли в списке использовавшихся числа из обоих массивов. если есть - то переходим к поиску второй суммы, гоу 1.
* 6. если нет - пусть так и валяется. по-хорошему надо удалять эти числа, но фиг с ними, проц мощный, справится
*
* 7. если разница +- погрешность не равна 0, продолжаем поиски. создаем у объекта все объекты из списка исходных, гоу 2.

Добавлено через 1 минуту
И тут же проблема чисел то исходных динамичное количество...
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
28.03.2014, 09:23
Цитата Сообщение от thisiswhite Посмотреть сообщение
И тут же проблема чисел то исходных динамичное количество...
Что значит динамическое количество?Вначале работы было к примеру 20,а потом в конец еще что-то добавили?
0
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
28.03.2014, 13:01  [ТС]
Не в смысле в начале работы разное количество бывает.
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
29.03.2014, 01:11
thisiswhite, пусть будет разное,для разных запусков,ничего страшного.
0
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
31.03.2014, 15:18  [ТС]
Вот такая вот пара классов получилась:
C#
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
/*
 * Сделано в SharpDevelop.
 * Пользователь: Михто
 * Дата: 27.03.2014
 * Время: 14:46
 *
 * Для изменения этого шаблона используйте Сервис | Настройка | Кодирование | Правка стандартных заголовков.
 */
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Threading;
 
namespace Load
{
 
 
    /*
     * есть 2 (любое число) массива чисел. нужно получить 2 (любое число) определенные суммы из этих чисел, обязательно (опционально) из обоих массивов.
     * для этого класс числа имеет свойство - к какому массиву он относится.
     *
     * алгоритм - рекурсивный перебор в ширину. то есть дерево с 1 вершиной.
     *
     * 
     * 1. создаем объект-обработчик. каждый объект будет представлять свой пусть вычислений.
     * 
     * у каждого из объектов-обработчиков есть 
     * - список всех исходных чисел - все числа из обих массивов
     * - список использовавшихся чисел 
     * - список вариаций использовавшихся чисел
     *
     * 2. перебираем все исходные числа, текущее i.
     * 3. создаем объект-обработчик, в котором удаляем i из списка исходных, добавляем i в список использовавшихся
     * 4. находим сумму всех использовавшихся чисел. если сумма +- погрешность больше искомой суммы, гоу 2.
     * 5. если использовавшиеся числа уже были, но в другом порядке, гоу 2   
     * 
     * 6. если сумму всех использовавшихся чисел +- погрешность равна 0, то нужная последовательность чисел найдена
     * 7. мы ее проверяем, есть ли в списке использовавшихся числа из обоих массивов. если есть - то переходим к поиску второй суммы, гоу 2.
     * 
     * 8. если сумму всех использовавшихся чисел +- погрешность не равна 0, продолжаем поиски. гоу 2.
     *
     *
     *
     */
 
 
    // класс чисел
    // содержит только значение числа и номер массива
    public class cNumber
    {
        // значение
        public double Value
        {
            get;
            private set;
        }
 
        // номер массива
        public int NumberArray
        {
            get;
            private set;
        }
        public int NumberRow
        {
            get;
            private set;
        }
 
 
        public cNumber(double _Value, int _NumberArray, int _NumberRow)
        {
            Value = _Value;
            NumberArray = _NumberArray;
            NumberRow = _NumberRow;
 
        }
 
    }
 
 
    // класс обработки чисел
    // каждый класс представляет ветвь вычислений
    public class cNumberProcess
    {
        public bool flag;
        // содержит решения
        public static List<cNumberProcess> RightSolutions = new List<cNumberProcess>();
 
        public static List<cNumber> lstDFO;
 
        // все ранее использовавшиеся числа
        // проверка IsAlreadyUsed
        List<string> AlreadyUsed = new List<string>();
 
 
        // просто счетчик
        public static double counter = 0;
 
        // список искомых сумм
        List<double> lstNeededSum;
        // номер в списке суммы, которую ищем сейчас
        double SumIndex;
 
        // требуемая сумма
        public double NeededSum
        {
            get
            {
                return lstNeededSum[int.Parse(SumIndex.ToString())];
            }
        }
 
        // максимальная погрешность
        public double ErrorValue;
 
        // сумма использовавшихся чисел
        public double SumUsed
        {
            get
            {
                double sumUsed = 0;
                foreach (var i in lstUsed)
                {
                    sumUsed += i.Value;
 
                }
                return sumUsed;
            }
        }
 
        // разница
        public double Difference
        {
            get
            {
                return (NeededSum - SumUsed);
 
            }
        }
 
        // если разница примерно равна 0, в пределах +- погрешности
        bool IsSumFounded
        {
            get
            {
                return (Math.Abs(Difference) <= ErrorValue);
            }
        }
 
        // если разница + погрешность меньше нуля, то ничего хорошего уже не случится. пора прекращать.
        bool IsVeryMuch
        {
            get
            {
                return ((Difference + ErrorValue) < 0);
            }
        }
 
        // использовались числа всех массивов?
        bool IsAllArrays
        {
            get
            {
                // находим число использовавшихся массивов
                List<int> lstArrayUsed = new List<int>();
                foreach (var i in lstUsed)
                {
                    if (!lstArrayUsed.Contains(i.NumberArray)) lstArrayUsed.Add(i.NumberArray);
                }
 
 
 
 
                // находим число исходных массивов
                // надо учесть, что из исходных массивов числа перемещены в список использовавшихся
                List<int> lstArraySource = new List<int>();
                foreach (var i in lstSource)
                {
                    if (!lstArraySource.Contains(i.NumberArray)) lstArraySource.Add(i.NumberArray);
                }
 
 
                foreach (var prev in lstPreviousSolutions)
                {
                    foreach (var i in prev.lstUsed)
                    {
                        // if (!lstArrayUsed.Contains (i.NumberArray )) lstArrayUsed.Add (i.NumberArray );
                        if (!lstArraySource.Contains(i.NumberArray)) lstArraySource.Add(i.NumberArray);
                    }
 
                }
 
                // если использовано массивов меньше, чем осталось, это однозначно фэил
                if (lstArrayUsed.Count < lstArraySource.Count)
                    return false;
 
                // если нет хоть одного массива, это фэил
                foreach (var i in lstArraySource)
                {
                    if (!lstArrayUsed.Contains(i)) return false;
                }
 
                return true;
 
 
            }
        }
        // список исходных
        List<cNumber> lstSource;
 
        // список использовавшихся
        public List<cNumber> lstUsed;
 
        // давно использовавшихся
        public List<cNumberProcess> lstPreviousSolutions = new List<cNumberProcess>();
 
        public cNumberProcess(List<double> _NeededSum, double _SumIndex, double _ErrorValue, List<cNumber> _lstSource, List<cNumber> _lstUsed, List<cNumberProcess> _lstPreviousSolutions, List<string> _AlreadyUsed, bool _flag)
        {
            flag = _flag;
            lstNeededSum = _NeededSum;
            SumIndex = _SumIndex;
            ErrorValue = _ErrorValue;
            lstSource = new List<cNumber>(_lstSource);
            lstUsed = new List<cNumber>(_lstUsed);
            lstPreviousSolutions = new List<cNumberProcess>(_lstPreviousSolutions);
            AlreadyUsed = _AlreadyUsed;
 
 
        }
 
 
 
        // страшная проверка
        // чтобы глупый комп не считал что "2, 3" и "3, 2" это разные наборы чисел
        bool IsAlreadyUsed()
        {
            // берем использовавшиеся числа
            var lst = new List<cNumber>(this.lstUsed);
 
            // сортируем их
            lst.Sort((a, b) =>
                     a.Value.CompareTo(b.Value));
 
            // переводим в строку
            string used = "";
            foreach (var i in lst)
            {
                used += i.Value.ToString() + "_" + i.NumberArray.ToString() + " ";
            }
 
            // строку ищем в списке
            bool res = AlreadyUsed.Contains(used);
            if (!res)
            {
                AlreadyUsed.Add(used);
            }
            return res;
        }
        Thread th;
        public void Tered()
        {
            th = new Thread(new ThreadStart(Recoursive));
            th.Start();
 
 
 
        }
 
        public void ShowcNumber(cNumberProcess _x)
        {
            lstDFO = new List<cNumber>();
 
            foreach (var j in _x.lstPreviousSolutions)
            {
 
                foreach (var k in j.lstUsed)
                {
                    lstDFO.Add(k);
                   
                }
            }
          
        }
        
        public static bool flagg;
        // рекурсивный метод
        public void Recoursive()
        {
            // перебираем все входные значения
            foreach (var i in this.lstSource)
            {
                if (this.flag == true)
                    break;
                cNumberProcess x = new cNumberProcess(lstNeededSum, SumIndex, ErrorValue, lstSource, lstUsed, lstPreviousSolutions, AlreadyUsed, false);
 
                x.lstSource.Remove(i);
                x.lstUsed.Add(i);
 
                // сумма чисел уже слишком большая
                if (x.IsVeryMuch)
                    continue;
 
                // данные числа уже использовались, но в других сочетаниях
                if (x.IsAlreadyUsed())
                    continue;
 
                // нашли последовательность
                // и используются элементы всех массивов
                if (x.IsSumFounded && x.IsAllArrays)
                //                if (x.IsSumFounded)
                {
 
                    // сохраняем это решение и будем искать дальше
                    x.lstPreviousSolutions.Add(new cNumberProcess(x.lstNeededSum, x.SumIndex, x.ErrorValue, x.lstSource, x.lstUsed, new List<cNumberProcess>(), new List<string>(), false));
 
                    double _SumIndex = x.SumIndex;
                    _SumIndex++;
 
                    // если больше нечего искать
                    if (_SumIndex >= x.lstNeededSum.Count)
                    {
                        // сохраняем решение в статичный массив
                        cNumberProcess.RightSolutions.Add(x);
                        ShowcNumber(x);
                        Stavka stavka = new Stavka();
                        flagg = false;
                        while (!flagg)
                        {
                            System.Threading.Thread.Sleep(100);
                        }
 
                        return;
                    }
                    else
                        // еще есть что искать
                        x.SumIndex++;
 
 
                    // обнуляем массив использовавшихся
                    x.lstUsed = new List<cNumber>();
                    x.AlreadyUsed = new List<string>();
                    if (flag != true)   // и ищем
                        x.Recoursive();
                }
 
                if (flag != true)  // ищем!
                    x.Recoursive();
 
            }
 
        }
    }
}
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
31.03.2014, 16:51
thisiswhite, и как,работает?
0
3 / 3 / 3
Регистрация: 26.02.2014
Сообщений: 49
31.03.2014, 17:18  [ТС]
Отлично!
0
1 / 1 / 0
Регистрация: 01.02.2014
Сообщений: 13
31.03.2014, 22:11
[url]
0
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
01.04.2014, 20:52
я думаю тут можно также применить идею Meet-in-the-middle.Идея вот в чём: все числа делятся на 2 части, и в каждой части генерируются все возможные суммы.А потом из этих сумм стараются получить сумму сумм как можно более близкую к искомому числу.Асимптотику такой подход нормально так уменьшает.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.04.2014, 20:52
Помогаю со студенческими работами здесь

Задача подбора слагаемых для нужной суммы
Нужно посчитать, каким количеством способов можно подобрать сумму, равную 18, используя следующие слагаемые: 10,6,1. При этом одни и те же...

DBGrid Получения текста нужной ячейки
Необходимо получить текст из нужной ячейки выделенной строки. Понимаю, что через событие OneCellClick? При этом в одном из параметров по...

Подбор значений для заданной суммы
Здравствуйте.Одна надежда на Ваш форум.Нужен макрос для следующей задачи.В диапазоне (В2:В10) - номера деталей. В диапазоне (С2:С10)-...

Конструкторы и деструкторы. Определить оптимальный подбор банкнот для выдачи задаваемой суммы в рублях для банкомата
Определить оптимальный подбор банкнот для выдачи задаваемой суммы в рублях для банкомата (купюры -1000, 5000, 10000, 20000, 50000)....

CRC32: Дополнить файл для получения контрольной суммы FFFFFFFF
Привет! Имеется произвольный бинарный файл. Цель: дополнить его как можно меньшим кол-вом байт, чтобы его КС по CRC32 стала =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru