Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
2 / 2 / 0
Регистрация: 15.01.2012
Сообщений: 181

Правильное и эффективное решение задачи на дп

31.03.2015, 21:39. Показов 2129. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Подскажите, пожалуйста, как решить данную задачу на динамическое программирование:

"Эффективный менеджер планирует построить несколько новых ресторанов вдоль шоссе. Есть n возможных мест, где можно построить ресторан, на расстояниях m1 < m2 <*< mn от начала шоссе. При этом:
1) В каждом из имеющихся n мест можно открыть не более одного ресторана;
2) Для каждого места i in [1,n] известна прибыль pi >0 от открытого там ресторана.
3) Любые два ресторана должны находиться на расстоянии не менее k километров, где k -положительное целое число.
Постройте эффективный алгоритм для расчёта максимальной общей прибыли при заданных условиях."

Пока всё, что пришло в голову:
S(j) - макс. прибыль от постройки отелей на отрезке [1,j],
S(1) = p1,
S(j) = Smax(j) + pj, где Smax(j) = макс. по i = 1,...,j-1 таких, что mj - mi >=k (если таких i нет, то Smax = 0),
Ответ - S(n);
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.03.2015, 21:39
Ответы с готовыми решениями:

Правильное ли решение задачи?
Найти массу груза,которую можно поднять медным тросом,состоящим из 50 проволок диаметром 2 мм ,если запас прочности = 3 , а механическое...

Правильное ли решение задачи?
Есть график V(t).Нужно составить график a(t) , определить путь и перемещение.Можете посмотреть,правильно ли я нашел путь и перемещение ? ...

Не могу найти правильное решение задачи
Массив из 10 элементов. Нужно вывести все элементы массива, которые находятся в интервале между средним и наименьшим значением. Среднее...

6
Модератор
Эксперт функциональных языков программирования
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,878
01.04.2015, 02:35
За линейное время.
Мне удобнее с конца строить решения. s[j] = прибыль с m[j] и до конца

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
void Main()
{
    
    int size = 10000000;
    var rnd = new Random();
    int k = 10;
    int minp = 10, maxp = 20;
    var m = new int[size];
    for(int i = 1; i < size; i++) m[i] = m[i-1] + 1 + rnd.Next(k); 
    var p = new int[size];
    for(int i = 0; i < size; i++) p[i] = rnd.Next(minp, maxp); 
    //Console.WriteLine("m = {0}", string.Join(", ", m));
    //Console.WriteLine("p = {0}", string.Join(", ", p));
    
    var timer = new Stopwatch();
    timer.Start();
    var res = CalculateProfit(m, p, k, false); 
    timer.Stop();
    Console.WriteLine("{0} ({1} ms)", res, timer.ElapsedMilliseconds);
}
 
private static int CalculateProfit(int[] m, int[] p, int k, bool isPrint = false)
{
    var maxp = p.Max(); // используем для отсечения
    var s = new int[m.Length]; 
    for(int j = m.Length-1; j >= 0; j--)
    {
        for(int i = j; i < m.Length; i++)
        {
            var res = p[i];
            var nextpos = i + 1; 
            while(nextpos < m.Length && m[nextpos] - m[i] < k) nextpos++;
            if(nextpos < m.Length) res += s[nextpos];
            if(res > s[j])
                s[j] = res;
            else if(res + maxp < s[j])
                break;
        }
        if(isPrint) Console.WriteLine(string.Join(", ", s));
    }
    return s[0];
}
1
194 / 174 / 30
Регистрация: 10.07.2012
Сообщений: 800
01.04.2015, 12:29
Лучший ответ Сообщение было отмечено PG94 как решение

Решение

PG94, все хорошо, только надо еще для каждого https://www.cyberforum.ru/cgi-bin/latex.cgi?j рассматривать вариант, когда мы вообще не строим ресторан в этой позиции.
это решение работает за https://www.cyberforum.ru/cgi-bin/latex.cgi?\mathcal{O}(N^2).
нужно заметить, что если рассматривать рестораны в порядке возрастания их координаты, то все допустимые рестораны (т.е те, которые находятся на расстоянии не меньше https://www.cyberforum.ru/cgi-bin/latex.cgi?k от текущего) - это непрерывный отрезок уже обработанных ресторанов. то есть нужно бинпоиском за https://www.cyberforum.ru/cgi-bin/latex.cgi?\mathcal{O}(logN) определить правую границу этого отрезка и найти минимум на соответствующем префиксе. минимум в данном случае ищется за https://www.cyberforum.ru/cgi-bin/latex.cgi?\mathcal{O}(1).
такое решение работает за https://www.cyberforum.ru/cgi-bin/latex.cgi?\mathcal{O}(N*logN). динамикой быстрее, скорее всего, решить невозможно. полезно определиться, существует ли жадное решение. скорее всего, его тоже нет.
2
221 / 166 / 47
Регистрация: 17.07.2012
Сообщений: 587
01.04.2015, 13:12
salam, вместо бинпоиска можно делать 2 указателя.
2
Модератор
Эксперт функциональных языков программирования
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,878
01.04.2015, 17:46
Цитата Сообщение от SlavaSSU Посмотреть сообщение
salam, вместо бинпоиска можно делать 2 указателя.
По-моему, второй указатель в худшем случае не поможет. Можно подобрать данные так, чтобы при сдвиге основного указателя на 1 второй указатель сдвигался на N-1.
А в среднем случае линейный поиск будет не хуже, чем второй указатель или бинарный.

з.ы. Это если я правильно понял Вашу мысль про второй указатель.

Добавлено через 2 минуты
Правда, всего второй указатель пробежит не больше N... тогда, выходит, поможет. Я запутался.

Добавлено через 17 минут
salam,
Поясните, пожалуйста, как Вы получаете такие оценки? (Какое решение работает за https://www.cyberforum.ru/cgi-bin/latex.cgi?\mathcal{O}(N^2)?)

Добавлено через 29 минут
Кажется, разобрался. Спасибо.

Добавлено через 11 минут
Теперь за линейное время не только в среднем, но и в худшем случае.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static int CalculateProfit2(int[] m, int[] p, int k, bool isPrint = false)
{
    var s = new int[m.Length]; 
    s[m.Length-1] = p[m.Length-1];
    int nextpos = m.Length;
    for(int j = m.Length-2; j >= 0; j--)
    {
        var res = p[j];
        while(m[nextpos-1] - m[j] >= k) 
            nextpos--;
        if(nextpos < m.Length) 
            res += s[nextpos];
        s[j] = Math.Max(res, s[j+1]);       
        if(isPrint) Console.WriteLine(string.Join(", ", s));
    }
    return s[0];
}
Вроде, всё правильно?

Добавлено через 1 час 25 минут
Избавился от одного сравнения внутри цикла. Так как сравнение хорошо предсказуемое, особого ускорения это не даёт, но код выглядит проще.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static int CalculateProfit3(int[] m, int[] p, int k, bool isPrint = false)
{
    var s = new int[m.Length+1]; 
    s[m.Length-1] = p[m.Length-1];
    int nextpos = m.Length;
    for(int j = m.Length-2; j >= 0; j--)
    {
        while(m[nextpos-1] - m[j] >= k) 
            nextpos--;
        s[j] = Math.Max(p[j] + s[nextpos], s[j+1]);       
        if(isPrint) Console.WriteLine(string.Join(", ", s));
    }
    return s[0];
}
0
2 / 2 / 0
Регистрация: 15.01.2012
Сообщений: 181
01.04.2015, 20:38  [ТС]
Спасибо. Думаю, что следующего исправления достаточно:
S(j) = max{S(j - 1), Smax(j) + pj}, где Smax(j) = max{S(i), i = 1,...,j-1 и mj - mi >=k}, если сущ. хотя бы одно такое i, иначе Smax(j) = 0.
Напишите, пожалуйста, если и в этот раз решение не полное.
0
Модератор
Эксперт функциональных языков программирования
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,878
01.04.2015, 21:05
Цитата Сообщение от PG94 Посмотреть сообщение
Спасибо. Думаю, что следующего исправления достаточно:
S(j) = max{S(j - 1), Smax(j) + pj}, где Smax(j) = max{S(i), i = 1,...,j-1 и mj - mi >=k}, если сущ. хотя бы одно такое i, иначе Smax(j) = 0.
Напишите, пожалуйста, если и в этот раз решение не полное.
По-моему, всё правильно.

С учётом того, что S(j) неубывающая функция, то вместо
Smax = max{S(i), i = 1,...,j-1 и mj - mi >=k}
можно использовать
S(maxi) = S(max{i, i = 1,...,j-1 и mj - mi >=k}).

И, как предложил SlavaSSU, можно использовать отдельные указатели для j и maxi. На каждом шаге увеличиваем j на 1, а maxi увеличиваем, пока не нарушается условие mj - mi >=k.

(как в вариантах CalculateProfit2 и CalculateProfit3)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
01.04.2015, 21:05
Помогаю со студенческими работами здесь

Правильное ли решение задачи линейного программирования
Здравствуйте! Правильно ли я решаю данную задачу и почему может не получаться график? Условие задачи: На ткацкой фабрике для...

Правильное ли решение задачи? Лафоре. 3 глава 9 задача
Представьте, что вы собираетесь пригласить к себе шестерых гостей, но за вашим столом могут разместиться всего лишь 4 человека Сколькими...

Подскажите эффективное решение
Сейчас делаю проект в котором надо управлять несколькими симисторами, естественно в схеме будет присутствовать детектор нуля для реализации...

Числа Каталана, самое эффективное решение
Здравствуйте. Есть типичная задача по числам каталана, пользователь вводит число н, нужно вывести число правильных возможных скобочных...

Какое эффективное решение , чтоб нужный код выполнялся раз в определенное время?
Например while(true) { Thread.Sleep(600000); .... } Но так вроде нельзя сделать даже на час задержку.


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru