Стрельба 1 Максимизация дистанции
創建於:2024年12月30日
創建於:2024年12月30日
Петя играет в одну простую игру под названием «Стрельба 1». Игра заключается в следующем – есть персонаж, который передвигается в плоском мире со скоростью 1 клетка в секунду и умеет стрелять из пистолета. Первоначально персонаж начинает движение с координаты 0 (двигаясь по одномерной оси) и имеет пистолет, который может достигать цели при стрельбе с расстояния 4 клетки, притом нанося препятствию 2 единицы урона в секунду. Также заранее известны координаты всех препятствий и их очки здоровья (ОЗ).
В игре есть возможность понизить здоровье одного любого препятствия до начала игры в два раза нацело (если было 5, станет 2; если 6, станет 3; если 1, станет 0), чтобы персонаж дошёл как можно дальше. Таким образом требуется помочь Пете определить, какому препятствию выгоднее всего убрать половину здоровья, чтобы персонаж прошёл как можно дальше.
Входные данные:
На вход на первой строке подаётся целое число L (1 <= L <= 100000) – длина оси, по которой будет передвигаться персонаж.
На второй строке подаётся целое число N (1 <= N <= 1000) – количество препятствий на оси.
Далее на N строках подаются целые координаты препятствий (целое число от 1 до L-1) и их ОЗ (целое число от 1 до 100) через пробел (например, 5 2, на координате 5 стоит препятствие с 2 ОЗ).
Выходные данные:
На выходе требуется вывести на первой строке координату препятствия, которому выгоднее всего понизить здоровье нацело в два раза, чтобы персонаж дошёл как можно дальше.
На второй строке вывести количество единиц, которое при этом пройдёт персонаж.
Примечание:
Если персонаж проходит весь маршрут и понижать здоровье никакому препятствию не требуется, вывести на первой строке 0, а на второй L.
Если персонаж может пройти одинаковое максимальное расстояние при понижении здоровья различным препятствям, то в выводе указать препятствие с самой большой координатой.
Когда персонаж не доходит до конца (упирается в препятствие, которое не успел уничтожить), то считается, что он прошёл ровно такое расстояние, на координате которой стояло препятствие (если персонаж закончил игру на препятствии по координате 9, то считается, что он прошёл 9 клеток).
Пример:
Входные данные
Выходные данные
15
3
3 6
5 4
9 10
9
15
Рассмотрим пример №1
Персонаж начинает с координаты 0, на расстоянии 3 есть препятствие с 6 ОЗ.
Персонаж сразу же может начать стрелять, так как расстояние меньше 4.
Придя на координату 3 – это препятствие будет уничтожено (нанося урон по 2 ОЗ).
Сразу же можно начать уничтожать препятствие по координате 5 (4 ОЗ). Как раз расстояние 2, потому оно будет уничтожено (выстрелом с координаты 3 и 4).
Препятствие по координате 9 имеет 10 ОЗ, значит оно не может быть уничтожено, но может быть понижено его здоровье в 2 раза в самом начале игры (есть возможность понизить ОЗ одного препятствия), таким образом, персонаж сможет дойти по оси до самого конца.
Чтобы решить задачу, необходимо определить, какое препятствие выгоднее всего понизить вдвое, чтобы персонаж мог пройти максимально возможное расстояние.
Понимание проблемы:
Алгоритм:
Инициализация: Для каждого препятствия вычисляем время, когда оно входит в зону стрельбы (t_start = max(x - 4, 0)
) и время, когда персонаж достигает его позиции (t_end = x
). Также рассчитываем необходимое время для уничтожения препятствия (D_i = ceil(H_i / 2)
).
Проверка начальной возможности:
t_end
.0
и L
.Оптимизация:
D_i
и проверяем, можно ли пройти весь маршрут с этим изменением.Реализация:
max_reachable
, которая проверяет, насколько далеко может пройти персонаж при заданных условиях.pythonimport math def ceil_div(a, b): return (a + b - 1) // b def max_reachable(obstacles_sorted, L): total_time = 0 for obs in obstacles_sorted: total_time += obs['D_i'] if total_time > obs['t_end']: return obs['x'] return L def main(): import sys import copy L = int(sys.stdin.readline()) N = int(sys.stdin.readline()) obstacles = [] for _ in range(N): x, H = map(int, sys.stdin.readline().split()) t_start = max(x - 4, 0) t_end = x D_i = ceil_div(H, 2) obstacles.append({'x': x, 'H': H, 't_start': t_start, 't_end': t_end, 'D_i': D_i}) # Sort obstacles by t_end obstacles_sorted = sorted(obstacles, key=lambda obs: obs['t_end']) # Compute initial max_reachable initial_reachable = max_reachable(obstacles_sorted, L) if initial_reachable >= L: print(0) print(L) return best_distance = initial_reachable best_x = 0 for i in range(N): obs = obstacles[i] H_halved = obs['H'] // 2 D_i_halved = ceil_div(H_halved, 2) if D_i_halved < obs['D_i']: # Create a deep copy of obstacles modified_obstacles = copy.deepcopy(obstacles) # Update the halved obstacle modified_obstacles[i]['H'] = H_halved modified_obstacles[i]['D_i'] = D_i_halved # Sort the modified obstacles by t_end modified_sorted = sorted(modified_obstacles, key=lambda o: o['t_end']) # Compute max_reachable reachable = max_reachable(modified_sorted, L) # Update best_x and best_distance if reachable > best_distance or (reachable == best_distance and obs['x'] > best_x): best_distance = reachable best_x = obs['x'] print(best_x) print(best_distance) if __name__ == "__main__": main()
ceil_div(a, b)
: Вычисляет деление с округлением вверх.max_reachable
: Проверяет, можно ли пройти все препятствия до конца маршрута L
, и возвращает максимальное достижимое расстояние.Входные данные:
text15 3 3 6 5 4 9 10
Выходные данные:
text9 15
Данный подход эффективно решает задачу, проверяя все возможные варианты понижения здоровья препятствий и выбирая оптимальный путь для прохождения маршрута.
Коля играет в одну простую игру под названием «Стрельба 2». Игра заключается в следующем – есть персонаж, который передвигается в плоском мире со скоростью М клеток в секунду и умеет стрелять из пистолета. Первоначально персонаж начинает движение с координаты 0 (двигаясь по одномерной оси) и имеет пистолет, который может достигать цели при стрельбе с расстояния K клетки, притом производя по U выстрелов в секунду, наносящих по 1 единицы урона. Также заранее известны координаты всех препятствий и их очки здоровья (ОЗ). Также на оси есть туманные области, которые не являются препятствиями, но стрельба через них понижает атаку персонажа в 2 раза нацело (если выстрел наносил 1 единицу урона, то будет 0; если 2, то 1; если 3, то 1; и т.д.).
Помогите Коле определить расстояние, которое пройдёт его персонаж по заданным входным параметрам.
Входные данные:
На вход на первой строке подаётся целое число L (1 <= L <= 100000) – длина оси, по которой будет передвигаться персонаж, целое число K (1 <= K <= L), целое число U (1 <= U <= 1000), целое число М (1<=М<=1000).
На второй строке подаётся целое число N (1 <= N <= 1000) – количество разрушаемых препятствий на оси.
Далее на N строках подаются целые координаты препятствий (целое число от 1 до L-1) и их ОЗ через пробел (например, 5 2, на координате 5 стоит препятствие с 2 ОЗ).
После на новой строке подаётся целое число D (1 <= D <= 1000) – количество туманных областей на оси.
Далее на D-строках подаются целые координаты тумана на оси (одно число от 1 до L-1).
Выходные данные:
На выходе требуется вывести одно целое число – расстояние, которое пройдёт персонаж.
Примечания.
Если персонаж проходит весь маршрут, то вывести L.
Когда персонаж не доходит до конца (упирается в препятствие, которое не успел уничтожить), то считается, что он прошёл ровно такое расстояние, на координате которой стояло препятствие (если персонаж закончил игру на препятствии по координате 9, то считается, что он прошёл 9 клеток).
Если при стрельбе пуля пролетает больше чем через одну туманную область, то считаем, что на её урон влияет только первая.
Персонаж каждую секунду останавливается и производит U выстрелов, если выстрел уничтожает цель и остались ещё выстрелы, которые могут долететь до следующего препятствия, то ему наносится урон.
Пример:
Входные данные
Выходные данные
15 3 1 1
3
3 3
5 2
9 6
1
4
5
Рассмотрим пример
Персонаж начинает с координаты 0, на расстоянии 3 есть препятствие с 3 ОЗ.
Персонаж сразу же может начать стрелять, так как расстояние K=3.
Придя на координату 3 – это препятствие будет уничтожено.
Далее есть препятствие по координате 5, но оно за туманом по координате 4, поэтому урон при стрельбе через него понижается нацело на 2 (1 единица урона становится равной 0). Прежний урон (1 ОЗ за выстрел) вернётся только после прохождения тумана (на координате 4). Но уничтожить препятствие он не успеет, так как требуется произвести 2 выстрела, а стреляет он раз в секунду, поэтому, игра закончится на расстоянии 5.
Чтобы помочь Коле определить максимальное расстояние, которое его персонаж сможет пройти в игре «Стрельба 2», необходимо тщательно проанализировать взаимодействие движения персонажа, стрельбы по препятствиям и влияния туманных областей на эффективность выстрелов. Ниже представлено пошаговое решение задачи с объяснением и реализацией на языке Python.
Основные компоненты игры:
Движение:
Стрельба:
Препятствия:
Туманные области:
Цель:
Определить максимальное расстояние, которое персонаж сможет пройти, уничтожив препятствия до их координат. Если невозможно уничтожить препятствие до его координаты, персонаж останавливается на его позиции.
Для эффективного решения задачи необходимо:
Предобработка данных:
Определение возможности уничтожения препятствий:
Расчет необходимого количества выстрелов:
Назначение времени выстрелов:
Определение максимального расстояния:
Сортировка данных:
Проверка возможности уничтожения препятствий:
Назначение времени выстрелов:
Вывод результата:
Ниже представлена реализация описанного алгоритма на языке Python:
pythonimport sys import math import bisect def main(): import sys import math # Чтение входных данных L_K_U_M = sys.stdin.readline().split() while len(L_K_U_M) < 4: L_K_U_M += sys.stdin.readline().split() L, K, U, M = map(int, L_K_U_M) N = int(sys.stdin.readline()) obstacles = [] for _ in range(N): parts = sys.stdin.readline().split() while len(parts) < 2: parts += sys.stdin.readline().split() x, H = map(int, parts) obstacles.append({'x': x, 'H': H}) D = int(sys.stdin.readline()) fog_positions = [] for _ in range(D): p = int(sys.stdin.readline()) fog_positions.append(p) fog_positions.sort() # Сортировка препятствий по координате obstacles.sort(key=lambda obs: obs['x']) # Определение максимально возможного времени T_max = (L + M - 1) // M + 1 # Добавляем 1 для безопасного индекса assigned = [False] * (T_max + 1) for obs in obstacles: x = obs['x'] H = obs['H'] # Проверка возможности уничтожения препятствия shooting_possible = False # Проверка всех возможных позиций y y_min = max(x - K, 0) y_max = x - 1 for y in range(y_max, y_min -1, -1): left = y + 1 right = x - 1 if left > right: # Нет позиций между y и x, значит тумана нет shooting_possible = True break # Проверка наличия тумана в диапазоне [left, right] idx = bisect.bisect_left(fog_positions, left) if idx < len(fog_positions) and fog_positions[idx] <= right: continue # Есть туман в пути else: # Нет тумана в пути от y до x shooting_possible = True break if not shooting_possible: # Невозможно уничтожить препятствие, остановиться на его координате print(x) return # Вычисление допустимого диапазона времени для стрельбы # t_start = ceil((x - K) / M) # t_end = ceil(x / M) -1 t_start = (x - K + M -1) // M t_start = max(t_start, 0) t_end = (x + M -1) // M -1 t_end = max(t_end, t_start) # Обеспечиваем, что t_end >= t_start # Количество необходимых выстрелов shots_needed = (H + U -1) // U # Назначение выстрелов как можно позже current_time = t_end for _ in range(shots_needed): while current_time >= t_start and assigned[current_time]: current_time -=1 if current_time < t_start: # Невозможно назначить все необходимые выстрелы print(x) return else: assigned[current_time] = True current_time -=1 # Если все препятствия уничтожены, персонаж достиг конечной точки print(L) if __name__ == "__main__": main()
Чтение входных данных:
Сортировка препятствий:
Назначение времени выстрелов:
Вывод результата:
Входные данные:
text15 3 1 1 3 3 3 5 2 9 6 1 4 5
Объяснение:
Препятствия:
Туманные области: 4 и 5
Параметры движения и стрельбы:
Процесс:
Препятствие 3:
Препятствие 5:
Вывод:
5
Данный алгоритм эффективно решает задачу, проверяя для каждого препятствия возможность его уничтожения и правильно распределяя время для выстрелов с учетом туманных областей. Жадный подход, назначающий выстрелы как можно позже в допустимом диапазоне времени, обеспечивает максимальную вероятность успешного уничтожения всех препятствий.