powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
13 сообщений из 38, страница 2 из 2
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37317674
Edd.Dragon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim111эхх, всё равно ничего не понятно...
Да не важно что именно сравнивать. Проблема в количестве вариантов. Для начал нужно придумать, как не перебирать все.
Еще и при условии, что массив нельзя сортировать.

А на что именно сравнивать получаемые разбиения - так пофигу. равнивай на что хочешь. Все-равно не дождешься конца выполнения, если будешь перебирать триллионы вариантов ))
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37318058
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В принципе, очень неплохих результатов можно добиться, воспользовавшись стохастическим методом.
В цикле из N попыток, случайно задаются сечения ряда и сравниваются тем или иным образом, например, по методу наименьших квадратов, качество попытки. В таком подходе нельзя гарантировать поиск наилучшего результата, зато за приемлимое время можно получить удовлетворительный результат.
Величина N находится эмпирически, с учетом мощности ПК
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37318565
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот когда еще я отписывал предыдущий пост - у меня был готовый вариант нахождения разбиения. Естественно, полным перебором, правда, с некоторыми улучшениями. Но я взял среднюю по мощности офисную машинку и погонял на ней свой расчет. На VBA.
Вообще, увеличение P на 1 приводило к возрастанию времени раза в 4, увеличение N вдвое - к увеличению времени раз в 40.
Поскольку даже тест N=30/P=7 работал 5 секунд, нецелесообразность была видна невооруженным глазом.

Пока раздумываю над новым алгоритмом...
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319078
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Жарко. Не спится.
Сделал вариант по предложенному стохастическому методу

Код: plaintext
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.
Option Explicit
Dim L

Public Function fragmentSeries(p As Integer, k As Long) As Double
    ' N - размерность массива
    ' L - массив
    ' P - количество частей (разбиений, фрагментов)
    ' k - число попыток
    
    Dim i, j, s, m, N, x, jj, minkv, sr, rndr, ss As String
    Dim rr()  ' массив размерностей фрагментов
    Dim minrr() As Integer ' найденный оптимальный массив размерностей фрагментов
    ReDim rr( 2 , p)
    ReDim minrr( 2 , p)
    
    Dim summ() As Double    ' массив сумм фрагментов
    Dim sumr() As Double
    ReDim summ(p)
    ReDim sumr(p)
    
    On Error GoTo errend
    fragmentSeries =  0 
    
    N = UBound(L)
    s =  0 
    For i = LBound(L) To N
        s = s + L(i)
    Next
    sr = s / p
    
    Randomize
    minkv =  9999999999999 #
    For i =  1  To k
        m =  0 
        For j =  1  To p
            rndr = Rnd(Now)
'            Debug.Print rndr
            rr( 1 , j) = m
            If j = p Then
                x = N
            Else
                x = m + Int(rndr * (N - (p - j) - m) +  0 . 5 )
                If x <  0  Then Stop
            End If
            rr( 2 , j) = x
        
            If rr( 2 , j) > UBound(L) Then Stop
        
            s =  0 
            For jj = rr( 1 , j) To rr( 2 , j)
                s = s + L(jj)
            Next
            summ(j) = s
            m = x +  1 
        Next
        s =  0 
        For jj =  1  To p
            s = s + (summ(jj) - sr) ^  2 
        Next
        If s < minkv Then
            For jj =  1  To p
                minrr( 1 , jj) = rr( 1 , jj)
                minrr( 2 , jj) = rr( 2 , jj)
                sumr(jj) = summ(jj)
            Next
            minkv = s
        End If
    Next
    
' Печатаем найденные оптимальные фрагменты ряда
    Debug.Print "Номер", "Лев.гран", "Прав.гран", "Сумма", "Ряд"
    For i =  1  To p
        ss = L(minrr( 1 , i))
            For j = minrr( 1 , i) +  1  To minrr( 2 , i)
            ss = ss & "-" & L(j)
        Next
        Debug.Print i, minrr( 1 , i), minrr( 2 , i), sumr(i), ss
    Next
    Exit Function
errend:
    fragmentSeries = Err.Number
End Function

Sub computate()
    Dim k, t1, t2, p As Integer, m As Long
    L = Array( 1 ,  2 ,  3 ,  7 ,  5 ) 
    t1 = VBA.Timer
    p =  3 
    m =  100000 
    k = fragmentSeries(p, m)
    If k <>  0  Then Debug.Print "Ошибка " & k
    t2 = VBA.Timer
    Debug.Print
    Debug.Print "Время исполнения="; t2 - t1; "сек. Ряд длиной " & UBound(L) +  1  & ", фрагментов " & p & ", попыток - " & m
End Sub


Номер         Лев.гран      Прав.гран     Сумма         Ряд
  1               0               2               6              1 - 2 - 3 
  2               3               3               7              7 
  3               4               4               5              5 

Время исполнения=  1 . 65625  сек. Ряд длиной  5 , фрагментов  3 , попыток -  100000 


Для ряда длиной 30, с числом разбиений на 5 фрагментов, время 3.2 сек. при том же числе испытаний
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319161
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо большое! Последний вариант работает быстро, делит хорошо!
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319179
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
эхх, хотя 191 элемент на 7 полок только что поделил - кривовато...
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319187
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim111эхх, хотя 191 элемент на 7 полок только что поделил - кривовато...
Исходный ряд покажите здесь.
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319194
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mds_world, 2 варианта - 1000000 и 10000000 попыток
как выложить, чтобы читабельно было?

Номер Лев.гран Прав.гран Сумма Ряд
1 0 13 143.5 7.5-14-9-16-8-7.5-11-7.5-13-7.5-13-7.5-13-9
2 14 29 153.5 9-9-14-7-8-8-8-16-7-7-7-7.5-16-9-8-13
3 30 48 199 9-6.5-11-9-10.5-10.5-10.5-10.5-14-7.5-15-8.5-8-8.5-7.5-16-14-6.5-16
4 49 68 205 16-12-8-14-11.5-11.5-11.5-7-8.5-16-8-8-8-14-6.5-14-6.5-9.5-8-6.5
5 69 86 177.5 16-8.5-6.5-14-8-15-7.5-16-11.5-6.5-9.5-7.5-14-8-8.5-6-8.5-6
6 87 109 225 8.5-8.5-8.5-8.5-7.5-14-16-14-7-5.5-9.5-11.5-11.5-19-9.5-7.5-7.5-7.5-7.5-11.5-7.5-9.5-7.5
7 110 124 167.5 9.5-11.5-11.5-7.5-9.5-15-15-19-16-16-6-14-7.5-9.5-0

Время исполнения= 0 сек. Ряд длиной 125, фрагментов 7, попыток - 1000000
Номер Лев.гран Прав.гран Сумма Ряд
1 0 17 182.5 7.5-14-9-16-8-7.5-11-7.5-13-7.5-13-7.5-13-9-9-9-14-7
2 18 35 171 8-8-8-16-7-7-7-7.5-16-9-8-13-9-6.5-11-9-10.5-10.5
3 36 49 158.5 10.5-10.5-14-7.5-15-8.5-8-8.5-7.5-16-14-6.5-16-16
4 50 66 174.5 12-8-14-11.5-11.5-11.5-7-8.5-16-8-8-8-14-6.5-14-6.5-9.5
5 67 88 209 8-6.5-16-8.5-6.5-14-8-15-7.5-16-11.5-6.5-9.5-7.5-14-8-8.5-6-8.5-6-8.5-8.5
6 89 105 172 8.5-8.5-7.5-14-16-14-7-5.5-9.5-11.5-11.5-19-9.5-7.5-7.5-7.5-7.5
7 106 124 203.5 11.5-7.5-9.5-7.5-9.5-11.5-11.5-7.5-9.5-15-15-19-16-16-6-14-7.5-9.5-0

Время исполнения= 0 сек. Ряд длиной 125, фрагментов 7, попыток - 10000000
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319198
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в некоторых массивах разброс значений небольшой, поэтому я вначале считал так:
увеличивал 1 фрагмент на 1 элемент массива, остальные фрагменты наполнял элементами, пока ширина фрагмента не превысит ширину 1 фрагмента.

Если в результате значения влазили в фрагменты, то отлично, в противном случае увеличивал 1 фрагмент ещё на 1 элемент(следующий по счёту) и заново пересчитывал.
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319514
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mds_worldVadim111эхх, хотя 191 элемент на 7 полок только что поделил - кривовато...
Исходный ряд покажите здесь.
Если эта работа реальная (а не учебная), то сначала перед разложением "элементов на полки", надо провести статистический анализ ряда. Поскольку число возможных размещений невероятно велико, то статанализ поможет сократить число возможных разбиений. В частности, при большой дисперсии данных, можно выбирать (и убирать из выборки) элементы большие чем среднее+3*сигма, где сигма - стандартное отклонение ряда. Все равно эти элементы заведомо потребуют для себя "отдельной полки". На основе статанализа, можно предложить и другие методы сократить пространство вариантов размещений.
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319590
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
работа реальная, выбирать и убирать нельзя
редко попадаются элементы толще чем 3 средних
мне нравится идея плясать от среднего, если, скажем число элементов больше какого то N
и полный перебор, если меньше, как то так может?
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319686
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim111работа реальная, выбирать и убирать нельзя
Дак не совсем убирать, а только на время подсчета. Ведь эти элементы все равно потребуют для себя отдельного размещения



Vadim111редко попадаются элементы толще чем 3 средних
Не три средних, а среднее+3 сигма. Например, есть ряд 10, 11, 12, 13, 14, 15, 80 , 10, 5, 6, 7, 8, 9, 1, 45 , 1, 5. Среднее этого ряда 14.8, сигма = 19.4. Среднее+3*сигма=73. И элемент 80 выводим из расчетов, запомнив его и подставив в окончательном выводе. А элемент 45 остается, хотя он и больше чем три средних. Но его вполне можно компоновать вместе с рядом стоящей единицей.



Vadim111мне нравится идея плясать от среднего, если, скажем число элементов больше какого то N
и полный перебор, если меньше, как то так может?
Да, такой алгоритм осуществим. Но требует немалой работы
...
Рейтинг: 0 / 0
разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
    #37319706
Vadim111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я грубо оценил, но можно и так - в массиве нету элементов, толще чем среднее + 3 сигма(
Видимо проще оценить, когда полный перебор занимает немного времени (1 вариант перебора - полный) , а когда - много - примерный вариант, предложенный Вами.

Хотя в обеих случаях мой метод с наращиванием 1 строки вполне живуч, ибо отклонение небольшое от среднего..
...
Рейтинг: 0 / 0
13 сообщений из 38, страница 2 из 2
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / разбить массив на n частей, чтобы длина массива макс. длины была минимальной)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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