Есть такая замечательная кроссплатформенная игрушка - Kerbal Space Program - симулятор космической программы, где нужно конструировать космические корабли и бороздить ими просторы вселенной, летая к другим планетам, строя космические станции и т.д. Для строительства кораблей доступно множество готовых частей (двигатели, топливные баки, кабины для космонавтов, вспомогательные маневровые двигатели, парашюты для посадки, крылья и закрылки, лестницы, солнечные батареи и всякое прочее), которые можно комбинировать множеством способов. Ваша задача - написать программу, которая получит на вход два ключевых параметра (масса полезного груза и delta-V бюджет) и придумает ракету наименьшей массы, способную поднять этот груз в космос и доставить его до цели, обеспечив требуемый бюджет скорости.
Delta-V бюджетДля космического корабля с выключенными двигателями, находящегося в гравитационном поле планеты или звезды, его дальнейшая судьба определяется только его скоростью и не зависит от массы и формы корабля. Если скорость не слишком велика, то в каждый момент времени он движется по орбите вокруг захватившего его небесного тела. Чтобы переместиться от одной планеты к другой, необходимо как минимум дважды поменять текущую орбиту: сперва перейти на эллиптическую орбиту, проходящую мимо обеих планет, затем перейти на орбиту вокруг новой планеты. Каждая такая смена орбиты есть изменение текущей скорости: к старому вектору скорости прибавляется некоторый корректирующий вектор ∆v и получается новый вектор скорости, соответствующий новой орбите. В промежутках между сменами орбит корабль летит по инерции и топливо не тратит. Стоит заметить, что эта ∆v не зависит от характеристик корабля и зависит только от маршрута: в каком месте с какой орбиты на какую переходим. При планировании межпланетной миссии составляется план маневров, и ∆v всех маневров суммируется в общий ∆v бюджет, который определяет, сколько нужно топлива: если его будет меньше, то пролететь по маршруту не получится, а если слишком много, то корабль выйдет излишне тяжелым и дорогим.
Расчет ∆vДля расчета изменения скорости при использовании ракетного двигателя используется уравнение Циолковского:∆v = log (m_start / m_end) * Isp * 9.816 где:
Структура ракетыИгра позволяет строить весьма разнообразные и причудливые корабли, но для упрощения расчетов и сужения пространства поиска мы введем ряд ограничений на их структуру. Ракета состоит из нескольких ступеней: при старте начинают работать двигатели первой, самой нижней, ступени, используя топливо из баков первой ступени. Когда топливо в них заканчивается, первая ступень (пустые баки и двигатели) отстреливаются специальным разделителем, после чего тут же начинают работу двигатели второй ступени. И так далее, пока не будет отброшена последняя ступень ракеты-носителя и не останется один лишь полезный груз (это может быть посадочный модуль со своими двигателями, но в рамках данной задачи это для нас неважно, важна лишь его масса). Каждая ступень состоит из опциональной центральной части (топливные баки и, обычно, двигатель), являющейся частью "ствола" ракеты, и 0, 2, 3, 4 или 6 боковых частей, также состоящих из топливных баков и опционального двигателя под ними. Т.е. всего возможны три формы ступени:
Каждая часть ступени (центральная или боковые) состоит из 1-3 топливных баков, поставленных вертикально друг на друга, и, опционально, двигателя под ними. В ступенях первой и третьей формы двигатели обязаны быть во всех частях. В ступени второй формы, состоящей из центральной части и N боковых, двигателей может быть либо 1 (только в центре), либо N+1 (везде). В пределах одной ступени все топливные баки и все двигатели одинаковые. Число баков во всех частях ступени тоже одинаковое.
Параметры всех двигателей и топливных баков перечислены здесь:
data Diam = Small | Large data Fuel = F String Float Float Diam -- name m_full m_empty size allFuels = [ F "FL-T100 Fuel Tank" 0.5625 0.0625 Small, F "FL-T200 Fuel Tank" 1.125 0.125 Small, F "FL-T400 Fuel Tank" 2.25 0.25 Small, F "FL-T800 Fuel Tank" 4.5 0.5 Small, F "Rockomax X200-8 Fuel Tank" 4.5 0.5 Large, F "Rockomax X200-16 Fuel Tank" 9 1 Large, F "Rockomax X200-32 Fuel Tank" 18 2 Large, F "Rockomax Jumbo-64 Fuel Tank" 36 4 Large] -- name size mass thrust Isp_atm Isp_vac data Engine = E String Diam Float Float Float Float allEngines = [ E "LV-T30 Liquid Fuel Engine" Small 1.25 215 320 370, E "LV-T45 Liquid Fuel Engine" Small 1.5 200 320 370, E "LV-909 Liquid Fuel Engine" Small 0.5 50 300 390, E "Toroidal Aerospike Rocket" Small 1.5 175 388 390, E "Rockomax \"Poodle\" Liquid Engine" Large 2.5 220 270 390, E "Rockomax \"Mainsail\" Liquid Engine" Large 6 1500 280 330, E "Rockomax \"Skipper\" Liquid Engine" Large 4 650 300 350, E "LV-N Atomic Rocket Engine" Small 2.25 60 220 800 ](масса в тоннах, тяга в килоньютонах) Между собой ступени соединяются разделителями. Вертикально они соединяются в стволе. Если двигатель верхней ступени и бак нижней ступени оба размера Large, то используется "Rockomax Brand Decoupler" массой 0.4 тонны. В противном случае используется "TR-18A Stack Decoupler" массой 0.05 тонны. Для горизонтального отделения боковых частей (разделения ступеней первой и третьей форм) используется "TT-38K Radial Decoupler" массой 0.025 тонны. Масса разделителя прибавляется к общей массе нижней (отделяемой) ступени. Замечание: двигатель "Toroidal Aerospike Rocket" не соединяется с разделителями, поэтому его нельзя использовать в центральной части, под которой будут другие ступени. Можно в боковых частях и можно в центральной части самой нижней ступени (хотя там он вряд ли пригодится). Остальные запчасти из того списка в вики игнорируйте, масса всех необходимых деталей будет включена в массу полезного груза. Формат решенияПрограмма должна получать на вход два вещественных числа: массу полезного груза в тоннах и Delta-V бюджет в м/с. На выход она должна выдать конфигурацию ступеней в порядке сверху-вниз (первой выводится ступень, отрабатывающая позже всех, последней выводится ступень, отрабатывающая раньше всех) в формате JSON-списка. Параметры одной ступени:
[ {"fuel": "FL-T400 Fuel Tank", "engine": "LV-N Atomic Rocket Engine", "central": true, "numSideParts": 3, "numEngines": 1, "height": 1}, {"fuel": "Rockomax X200-16 Fuel Tank", "engine": "LV-T30 Liquid Fuel Engine", "central": true, "numSideParts": 2, "numEngines": 3, "height": 1}, {"fuel": "Rockomax X200-8 Fuel Tank", "engine": "Rockomax \"Skipper\" Liquid Engine", "central": true, "numSideParts": 4, "numEngines": 5, "height": 1} ]Число ступеней должно быть не больше 7. И сумма высот (числа баков по вертикали) всех ступеней со стволом не должна быть больше 7. Т.е. всего в ракете-носителе может быть максимум 7 ступеней единичной высоты. Или две стволовых ступени по 3 бака, одна ступень с одним, и сколько-то чисто боковых. А может быть всего лишь две ступени по два бака, например, т.е. общая высота может быть и меньше 7.
Общий запас delta-V для ракеты определяется как сумма delta-V всех ступеней. При расчете
∆v одной ступени следует учитывать, что m_start есть сумма массы полезного груза, массы
всех следующих (по времени) ступеней и массы текущей ступени при полных баках. m_end - то
же, но уже с пустыми баками текущей ступени. Суммарное значение ∆v должно получиться
больше или равным заданному на входе требуемому бюджету. При этом следует минимизировать
суммарную массу всей ракеты. При расчете ∆v следует брать Isp двигателя в вакууме для всех
ступеней кроме стартовой (последняя в выводимом списке), для которой следует использовать
значение Isp в атмосфере. Считаем, что первые 5000 В игровую физику также входит сопротивление воздуха, но мы им в этой задаче пренебрежем.
Проверить решение и сравнить расчеты по ракете можно здесь: Решение ваша программа должна находить за 2 минуты. Присылайте конфигурации, найденные вашей программой для таких параметров:
|
|