Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308

Оптимальный алгоритм максимизации для игры

28.03.2023, 14:34. Показов 854. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Игра довольно простая. Есть последовательность чисел A длины N, есть два игрока И1 и И2, которые последовательно берут по числу. Игроки ходят поочередно, но И1 начинает игру всегда первым. Смысл игры - набрать максимальную сумму чисел. И1 на своем ходу может взять 1 число или пропустить ход. Также один раз за всю игру И1 может взять 2 числа. И2 играет всегда "глупо" - берет 1 число на своем на своем ходу. Смысл задачи - просчитать максимально возможный выигрыш для И1.
Пример:
A= [69 81 71 18 35 28 12 63 5 54]
Жирным выделены числа, которые забрал И1. Результат - 320.
Ограничения N <= 105, 0 <= Ai <= 100

Я потратил кучу времени на эту казалось бы простую задачу. Но лучше метода ветвей и границ ничего не придумал, но он не проходит по времени для больших N. Я думаю, что ограничения, которые наложены на числа тут неспроста и это надо использовать, но идей нет. Буду рад дельным советам.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.03.2023, 14:34
Ответы с готовыми решениями:

Оптимальный алгоритм для вызова хранимых процедур с разными аргументами для отчетов
Есть база данных, в ней расположены хранимые процедуры с входящими параметрами Требуется разработать клиент-приложение, которая будет...

Алгоритм максимизации функции дихотомическим поиском
Добрый вечер! Подскажите, как реализовать алгоритм максимизации функции дихотомическим поиском?

Машина Поста: найти сумму натуральных чисел от 1 до 10, используя оптимальный алгоритм для нахождения данной суммы
Составить машину Поста оптимального решения сдедующей задачи - найти сумму натуральных чисел от 1 до 10, используя оптимальный алгоритм...

6
3 / 2 / 1
Регистрация: 28.03.2023
Сообщений: 5
28.03.2023, 15:14
Действительно, метод ветвей и границ может быть не очень для данной задачи из-за большого количества возможных вариантов ходов. Вместо этого, Америку я тут не открою, можно попробовать динамическое программирование.

Пусть dp[i][j] - это максимальная сумма, которую может набрать И1, если осталось взять числа с индексами от i до N-1, а И1 уже взял j чисел на предыдущих ходах. Тогда, чтобы вычислить dp[i][j], нужно рассмотреть два варианта:

1. И1 пропускает ход: dp[i][j] = dp[i+1][j].
2. И1 берет одно число: dp[i][j] = dp[i+1][j+1] + A[i].
3. И1 берет два числа: dp[i][j] = dp[i+2][j+2] + A[i] + A[i+1].

Изначально, dp[N][j] = 0 для всех j, так как если не осталось чисел, то сумма равна 0. Также, dp[i][j] = -inf для всех j > N-i, так как И1 не может взять больше чисел, чем осталось.

Итоговый ответ будет равен dp[0][0].

Вот пример кода на Python:

N = int(input())
A = list(map(int, input().split()))

# Инициализация массива dp
dp = [[-float('inf')] * (N+1) for _ in range(N+1)]
for j in range(N+1):
dp[N][j] = 0
for i in range(N):
for j in range(N-i+1):
if j > 0:
dp[i][j] = max(dp[i][j], dp[i+1][j-1] + A[i])
dp[i][j] = max(dp[i][j], dp[i+1][j])
if j < N-i-1:
dp[i][j] = max(dp[i][j], dp[i+2][j+2] + A[i] + A[i+1])

print(dp[0][0])


Этот код работает за время O(N^2) и должен быть более-менее быстрым для заданных ограничений, наверное...
1
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
28.03.2023, 15:51  [ТС]
Спасибо, пошел переваривать. У меня мало опыта использования динамического программирования, но попытаюсь понять идею. Боюсь, что N2 все же все равно слишком долго окажется.

Добавлено через 16 минут
Код вроде как нерабочий, но я все же попытаюсь понять идею)
0
Модератор
Эксперт функциональных языков программирования
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,879
28.03.2023, 19:05
1. Для каждой позиции, начиная с конца, посчитать максимальную сумму без использования суперхода.
s[i] = max (a[i] + s[i+2], s[i+1])

2. Для каждой позици, начиная с начала, посчитать максимальную сумму с использованием суперхода в данной позиции.
s[k] = a[k] + a[k+1] + s[k+3]
Далее аналогично пункту 1, начиная с позиции k-1.

Получаем квадратичное время.
Подозреваю, что можно справиться за линейное время с использованием двух дополнительных массивов, но доказать не могу. Так что, возможно, нельзя.

Добавлено через 1 минуту
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var a = new int[] { 69, 81, 71, 18, 35, 28, 12, 63, 5, 54, 0, 0 };
int n = a.Length - 2;
 
var s = new int[a.Length];
for (int i = n - 1; i >= 0; i--)
{
    s[i] = Math.Max(a[i] + s[i + 2], s[i + 1]);
}
 
var smax = 0;
for (int k = 0; k < n - 1; k++)
{
    s[k] = a[k] + a[k + 1] + s[k + 3];
    for (int i = k - 1; i >= 0; i--)
    {
        s[i] = Math.Max(a[i] + s[i + 2], s[i + 1]);
    }
    if (s[0] > smax)
    {
        smax = s[0];
    }
}
Console.WriteLine(smax);
1
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
28.03.2023, 19:42  [ТС]
Почитал про динамическое программирование - голова опухла, много всяких умных формул, а я не математик. А что в универе было уже забыл за много лет
Короче я сам дошел до решения за O(N). Вернулся к исследованию переборочного варианта (сперва я ушел не в ту сторону на метод ветвей и границ), заметил, что много повторных вычислений в узлах дерева. Решил переделать на поиск в глубину, это позволило дать возможность закэшировать результаты вычислений. Потом в процессе отладки до меня дошло, что по факту тут хвостовая рекурсия, которую можно развернуть:
Python
1
2
3
4
5
6
7
8
9
10
n = int(input(''))
v = [int(x) for x in input('').split()]
r1 = [0] * (n + 3)
r2 = [0] * (n + 3)
r1[n - 1] = v[n - 1]
r2[n - 1] = v[n - 1]
for i in reversed(range(0, n - 1)):
    r1[i] = max(v[i] + r1[i + 2], r1[i + 1], v[i] + v[i + 1] + r2[i + 3])
    r2[i] = max(v[i] + r2[i + 2], r2[i + 1])
print(r1[0])
Проходит все тесты макс. за 70мс при допустимой 1 сек. С этой задачей мне попросил помочь знакомый студент. Лично мое мнение - препод издевается.
1
Модератор
Эксперт функциональных языков программирования
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,879
28.03.2023, 22:58
Цитата Сообщение от shmkv Посмотреть сообщение
Лично мое мнение - препод издевается.
Почему издевается? Отличная задача.
0
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
29.03.2023, 00:14  [ТС]
Мне кажется избыточно сложно прийти к такому решению для рядового студента.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.03.2023, 00:14
Помогаю со студенческими работами здесь

Определить цену игры, оптимальный план
решить задачу по теории игр, игры с &quot;природой&quot;. При крупном автомобильном магазине планируется открыть мастерскую по предпродажному...

оптимальный алгоритм
найти сумму простых чисел от 1 до A program kl; var s,m,p,n,A:integer; begin read (A); for n:=1 to A do begin p:=1; for...

Алгоритм для игры
Народ, кто знает алгоритм проверки конца игры в игре &quot;Четыре в ряд 7х6&quot; Цель игры — расположить раньше противника подряд по горизонтали,...

Оптимальный алгоритм сортировки
Доброго времени суток! Есть некий класс: public class Person { public string Name { get; set; } public int Age {...

Оптимальный алгоритм сортировки
Камрады! Есть функция/процедура f(m,n), которая получает 2 номера и возвращает n,m (n&gt;m) т.е. &quot;сортирует&quot; от большего...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru