Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Максимальный подмассив массива, алгоритм с высокой скоростью 
:(
    Опции темы
46&two
Дата 18.11.2004, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 6.2.2004

Репутация: нет
Всего: нет



Решения этой (распространенной видимо) задачи на alglib я не нашел.
Зaдача такая:
есть массив целых (положительных и отрицательных) чисел A длиной N.
Нужно найти такие m и k, что A[m] + A[m+1] + .... A[m+k] максимально.
При этом построенный алгоритм должен иметь вычислительную сложность O(N).
Есть ли какие мысли?
PM MAIL   Вверх
val
Дата 18.11.2004, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Подумал и пришел к тому, что минимальное кол-во операций порядка n*k. Лучше не придумал. Если такое решение подходит, напишу алгоритм...

Это сообщение отредактировал(а) val - 18.11.2004, 19:23


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 18.11.2004, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



когда мне пришел в голову этот алгоритм, я попытался объяснить его коллеге и вдруг понял, что перевести его на C++ мне оказалось легче, чем на русский smile
Код

#include <iostream.h>

int array[]={2,-3,14,-1,2,-3,2,-15,5,-1,6,-1,12};
int maxend,maxbegin,maxsum;
void main()
{
 int end,begin,sum;
 maxend=1;
 maxbegin=0;
 maxsum=array[0];
 end=0;
 begin=0;
 sum=0;
 while(end<=sizeof(array)/4)
 {
   //try to shift begin
   if(sum<0)
   {
     begin=end;
     sum=0;
   }
   //shift end
   end++;
   sum+=array[end-1];
   if(sum>maxsum)
   {
     maxend=end;
     maxbegin=begin;
     maxsum=sum;
   }
 }
 cout<<maxbegin<<"\n";
 cout<<maxend-1<<"\n";
 cout<<maxsum<<"\n";
}

но все-таки немного пояснений:
есть два отрезка: текущий и оптимальный
у каждого отрезка есть два маркера: начальный и конечный
сначала текущий отрезок состоит только из одного элемента (первого)
потом начинаем двигаем правый маркер (и соответственно прибавляем элементы, которые встречаем, к текущей сумме) на один
на каждом шаге сравниваем текущий отрезок с оптимальным, если лучше - переписываем
после этого на каждом шаге проверяем не стала ли сумма по отрезку меньше нуля
если это так, то этот отрезок только испортит ситуацию в будущем, поэтому отрезаем его и делаем begin=end
в конце получаем оптимальный отрезок...


--------------------
qqq
PM WWW   Вверх
46&two
Дата 19.11.2004, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 6.2.2004

Репутация: нет
Всего: нет



maxim1000, а что будет, если все элементы массива отрицательны? не получится ли max = a[0]?
PM MAIL   Вверх
val
Дата 19.11.2004, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Программа выдаёт:
8
13
31


К сожалению, у нас нет 13-ого элемента...

В контекте данного решения надо выводить end - 2? то есть:
Код

 cout<<maxend-2<<"\n";


Ну сумма, наверно должна быть 5 + (-1) + 6 +(-1) + 12 = 21.
Что не сходится...
Если все числа отрицательны, то программа, к сожалению, выдаёт совсем не то, что надо... smile

Прошу прощения за критику... smile

Это сообщение отредактировал(а) val - 19.11.2004, 11:13


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 19.11.2004, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(46 @ 19.11.2004, 08:07)
maxim1000, а что будет, если все элементы массива отрицательны? не получится ли max = a[0]?

согласен...
просто надо сначала пройтись по массиву и найти максимальный элемент
если он отрицательный - вывести его и выйти
на порядок сложности это не повлияет
Цитата(val @ 19.11.2004, 10:11)
К сожалению, у нас нет 13-ого элемента...

честно говоря, не понял...
где нет 13-го элемента?
Цитата(val @ 19.11.2004, 10:11)
В контекте данного решения надо выводить end - 2? то есть:

в этой программе за end принято номер первого элемента справа от отрезка, т.е. отрезок на самом деле является полуинтервалом: [begin;end), а если нужно описать конец отрезка, нужно отнять 1...
Цитата(val @ 19.11.2004, 10:11)
Прошу прощения за критику...

если бы мне не была интересна критика этой программы, я бы, наверное, и не выкладывал ее smile

Это сообщение отредактировал(а) maxim1000 - 19.11.2004, 11:55


--------------------
qqq
PM WWW   Вверх
val
Дата 19.11.2004, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Цитата
честно говоря, не понял...
где нет 13-го элемента?


На вопрос ответил ниже:
Цитата
отрезок на самом деле является полуинтервалом: [begin;end), а если нужно описать конец отрезка, нужно отнять 1...









--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
manu
Дата 19.11.2004, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 14.10.2004

Репутация: нет
Всего: 3



int a[10]={...},n;

struct A {
int begin,end,sum;
};

// 1. если все элементы не положительны, то искомый отрезок -- максимальный элемент a
bool check() {
int i, maxval,maxpos;

for(i=0; i<n; i++) if(a[n]>0) return false;

max=a[0];
for(i=1; i<n; i++) if(a[i]>max) {
max=a[i];
}

// 2. считаем суммы положительных и отрицательных отрезков


int
PM   Вверх
46&two
Дата 19.11.2004, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 6.2.2004

Репутация: нет
Всего: нет



manu, будь добр, заверши идею. smile
PM MAIL   Вверх
val
Дата 22.11.2004, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



maxim1000 с такими входными данными твоя программка не работает...
Код

int array[]={-5, -1, 2, 4, -16};



Это сообщение отредактировал(а) val - 22.11.2004, 13:41


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 22.11.2004, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(val @ 22.11.2004, 12:40)
maxim1000 с такими входными данными твоя программка не работает...

не знаю, у меня выдает 2, 3, 6


--------------------
qqq
PM WWW   Вверх
manu
Дата 22.11.2004, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 14.10.2004

Репутация: нет
Всего: 3



Цитата(46 @ 19.11.2004, 13:41)
manu, будь добр, заверши идею. smile

я начал писать, потом понял, что мое решение не подходит, а сообщение почему-то запостилосьЖ)
я думаю, что когда мы двигаем начало, то надо двигаться не на длину всего отрезка, а на 1 позицию.
PM   Вверх
val
Дата 22.11.2004, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Код

#include <iostream.h>

int array[]={-5, -1, 2, 4, -16};
int maxend,maxbegin,maxsum;
void main()
{
int end,begin,sum;
maxend=1;
maxbegin=0;
maxsum=array[0];
end=0;
begin=0;
sum=0;
while(end<=sizeof(array)/4)
{
  //try to shift begin
  if(sum<0)
  {
    begin=end;
    sum=0;
  }
  //shift end
  end++;
  sum+=array[end-1];
  if(sum>maxsum)
  {
    maxend=end;
    maxbegin=begin;
    maxsum=sum;
  }
}
cout<<maxbegin<<"\n";
cout<<maxend-1<<"\n";
cout<<maxsum<<"\n";
}


У меня этот код выдаёт
5,
5,
10



--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 22.11.2004, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



я специально скопировал код в новый проект: 2,3,6
у меня VisualStudio 6.0, а у тебя?


--------------------
qqq
PM WWW   Вверх
val
Дата 22.11.2004, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Цитата
я специально скопировал код в новый проект: 2,3,6
у меня VisualStudio 6.0, а у тебя?


Visual Studio. NET 7.0.


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 22.11.2004, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



попробуй вместо sizeof(array)/4 вручную записать количество элементов
(а то у меня такое ощущение, что происходит выход за границы массива)


--------------------
qqq
PM WWW   Вверх
val
Дата 22.11.2004, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: 1
Всего: 7



Поменял, нет не работает. Ладно, с логикой всё Ок, это главное... smile


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
3,14
Дата 22.11.2004, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1614
Регистрация: 18.6.2004
Где: Н. Новгород

Репутация: нет
Всего: 24



Собственно- вот мой вариант (необессудьте на опечатки, код не тестил, пишу на вскидку):
Код

int max_ k = k = 1;
int max_sum = sum = a[0];
int max_m = m = 0;
for(int j = 1; j < n; j++)
{
 if (sum < 0)
 {
    sum = a[j];
    m = j;
    k = 1;
 }
 if (a[j] < 0)
 {
    if (sum > max_sum)
    {
       max_sum = sum;
       max_k = k
       max_m = m;
    }
    sum = <САМОЕ МАЛЕНЬКОЕ ИЗ ДОПУСТИМЫХ>;
 }
 else
 {
    sum += a[j];
    k++;
 }
}
if (sum > max_sum)
{
  max_sum = sum;
  max_k = k
  max_m = m;
}
//вывод

Вроде должно работать

Это сообщение отредактировал(а) 3,14 - 22.11.2004, 22:46


--------------------
Может быть, это только мой бред,
Может быть, жизнь не так хороша,
Может быть, я не выйду на свет,
Но я летал, когда пела душа...
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.