import System.IO import Control.Monad import Data.Function import Data.List import Data.IORef infinity :: Floating a => a infinity = 1.0/0.0 main :: IO () main = do hSetBuffering stdout NoBuffering -- DO NOT REMOVE -- Auto-generated code below aims at helping you parse -- the standard input according to the problem statement. input_line <- getLine let n = read input_line :: Int -- the number of points used to draw the surface of Mars. pts <- replicateM n $ do input_line <- getLine let input = words input_line let land_x = read (input!!0) :: Int -- X coordinate of a surface point. (0 to 6999) let land_y = read (input!!1) :: Int -- Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars. return (land_x, land_y) let flats = [ ((x0, x1, y0), x1-x0) | ((x0,y0),(x1,y1)) <- zip pts (tail pts), y1 == y0 ] let ((lzX0, lzX1, lzY), _) = maximumBy (compare `on` snd) flats lostPower <- newIORef (0.0, 0.0) fix $ \loop -> do input_line <- getLine let input = words input_line let x = read (input!!0) :: Int let y = read (input!!1) :: Int let hs = read (input!!2) :: Int -- the horizontal speed (in m/s), can be negative. let vs = read (input!!3) :: Int -- the vertical speed (in m/s), can be negative. let f = read (input!!4) :: Int -- the quantity of remaining fuel in liters. let r = read (input!!5) :: Int -- the rotation angle in degrees (-90 to 90). let p = read (input!!6) :: Int -- the thrust power (0 to 4). -- hPutStrLn stderr "Debug messages..." let currentX = fromIntegral x let currentY = fromIntegral y let targetX = fromIntegral (lzX0 + lzX1) / 2.0 let targetY = fromIntegral lzY + 50 let veloX = fromIntegral hs let veloY = fromIntegral vs let accelX = fromIntegral p * sin (pi * fromIntegral (-r) / 180) let accelY = fromIntegral p * cos (pi * fromIntegral (-r) / 180) let maxAccelY = 0.1 let decelTimeY = if veloY >= 0 then 0 else (-veloY) / maxAccelY let decelDistY = (-veloY) * decelTimeY - 0.5 * maxAccelY * decelTimeY^2 let descend = currentY - targetY > decelDistY || (currentX >= fromIntegral lzX0 + 100 && currentX <= fromIntegral lzX1 - 100 && abs veloX <= 40) let targetVeloY = if currentY > targetY + 300 then -60 else if descend then -30 else if currentY < targetY then 4 else 0 let projectedY = currentY + veloY * (2 * (targetX - currentX) / veloX) let minAccelY = 3.711 + (38^2 + 38 * veloY) / (targetY - projectedY) let accelY' = min 3.95 $ max minAccelY $ if targetVeloY < veloY then 0 else 3.711 + min maxAccelY (0.04 * (targetVeloY - veloY)) let rangeX = if accelY' >= 4 then 0.0 else sqrt (4^2 - accelY'^2) let decelTimeX = if rangeX < 0.001 then infinity else abs veloX / rangeX let projectedX = currentX + veloX * decelTimeX - 0.5 * (signum veloX * rangeX) * decelTimeX^2 let accelX' = if projectedX > fromIntegral lzX1 - 200 then -rangeX else if projectedX < fromIntegral lzX0 + 200 then rangeX else max (-rangeX) $ min rangeX $ 0.2 * (-veloX) (lpX, lpY) <- readIORef lostPower let landing = currentX >= fromIntegral lzX0 && currentY <= fromIntegral lzX1 && currentY <= fromIntegral lzY + 100 let angle' = if landing then 0 else (atan2 (accelY'+lpY) (accelX'+lpX) * (180.0/pi)) - 90 let rightDirection = max 0 $ cos (pi / 180 * (fromIntegral r - angle')) let power' = rightDirection * sqrt ((accelX'+lpX)^2 + (accelY'+lpY)^2) let p' = max 0 $ min 4 $ round power' let r' = max (-90) $ min 90 $ truncate $ angle' let accelX'' = fromIntegral p' * sin (pi * fromIntegral (-r') / 180) let accelY'' = fromIntegral p' * cos (pi * fromIntegral (-r') / 180) writeIORef lostPower (0.8*(accelX'-accelX''), 0.8*(accelY'-accelY'')) -- R P. R is the desired rotation angle. P is the desired thrust power. putStrLn $ show r' ++ " " ++ show p' loop