业余Haskell爱好者,欢迎大家前来讨论,有啥说啥
StateT [((Double 开始点, Double 结束点, Double 单价), Double 加油点)] (Reader Double 最大油耗) ()
module Main where
import Control.Monad
import Control.Monad.Reader
import Control.Monad.State
import Data.List
import Text.Printf
main :: IO ()
main = do
[d1, c, d2, p, n] <- fmap read . words <$> getLine
disToPrice <- fmap (([0, p] :) . sort . ([d1, 0] :)) $ replicateM (truncate n) $ fmap read . words <$> getLine
let preprocessing = fmap (\([d0, p0], [d1, _]) -> (d0 / d2, d1 / d2, p0)) $ zip disToPrice $ tail disToPrice
putStrLn $
if (> 0) . length . filter (\(d0, d1', _) -> (d1' - d0) > c) $ preprocessing
then "No Solution"
else printf "%.2f\n" . sum . fmap (\((d0, d1, p), _) -> (d1 - d0) * p) . flip runReader c . flip execStateT mempty $ foldl1' (>>) $ calc <$> preprocessing
calc :: (Double, Double, Double) -> StateT [((Double, Double, Double), Double)] (Reader Double) ()
calc disAndPrice@(d0, _, p) = do
preDisAndPrices <- get
if null preDisAndPrices
then put [(disAndPrice, 0)]
else do
let pre@((_, _, pp), _) = head preDisAndPrices
if p <= pp
then do
modify (((disAndPrice), d0) :)
else myMerge disAndPrice
myMerge :: (Double, Double, Double) -> StateT [((Double, Double, Double), Double)] (Reader Double) ()
myMerge curDAP@(d0, d1, p) = do
maxCapacity <- ask
preDisAndPrices <- get
let (preDAP@((pd0, pd1, pp), ps) : daps) = preDisAndPrices
if d1 - ps <= maxCapacity
then put $ ((pd0, d1, pp), ps) : daps
else put $ ((pd0 + maxCapacity, d1, p), d0) : ((pd0, pd0 + maxCapacity, pp), ps) : daps