一开始感觉仅有输入不同,所以试了试仅修改处理输入数据的函数,没想到直接通过了,开心!! (*^▽^*)
第一次使用 Monad Transformer, 劳烦大佬们看看是否正确, 谢谢Thanks♪(・ω・)ノ
相较于 P1006题解 - haskell初学者,求大佬指教写法思路 仅修改了
getAllWeightedPoint函数及其调用
module Main where
import Control.Monad.Reader (MonadReader (ask), ReaderT (runReaderT), liftIO)
import Control.Monad.State (MonadState (get), State, evalState, modify)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
main :: IO ()
main = do
[m, n] <- fmap read . words <$> getLine
weightedPoints <- runReaderT getAllWeightedPoint m
putStrLn
. show
. flip evalState mempty
. flip runReaderT (weightedPoints, (m, n))
$ (dfs (1, 0) (1, 0))
type Point = (Int, Int)
type WeightedPoints = M.Map Point Int {- Weight -}
getAllWeightedPoint :: ReaderT Int {- lengthOfRow -} IO WeightedPoints
getAllWeightedPoint =
M.fromList <$> getAllLines 1
where
getAllLines lineNum = do
lengthOfRow <- ask
if lineNum > lengthOfRow
then return []
else do
matrixRow <- fmap read . words <$> liftIO getLine
(zip (zip (repeat lineNum) [(1 :: Int) ..]) matrixRow ++) <$> getAllLines (lineNum + 1)
type Cache = M.Map (Point, Point) Int
dfs :: Point -> Point -> (ReaderT (WeightedPoints, Point) (State Cache) Int)
dfs pfst@(xfst, yfst) psnd@(xsnd, ysnd) = do
cache <- get
(weightedPoints, targetPoint) <- ask
case M.lookup (pfst, psnd) cache of
Just v -> return v
Nothing -> do
dd <- nextStep (xfst + 1, yfst) (xsnd + 1, ysnd)
dr <- nextStep (xfst + 1, yfst) (xsnd, ysnd + 1)
rd <- nextStep (xfst, yfst + 1) (xsnd + 1, ysnd)
rr <- nextStep (xfst, yfst + 1) (xsnd, ysnd + 1)
let max' = maximum [dd, dr, rd, rr]
modify $ M.insert (pfst, psnd) max'
return max'
where
nextStep pnfst pnsnd =
if isPointInBounds pnfst targetPoint && isPointInBounds pnsnd targetPoint
then (addWeight pnfst) . (if (pnfst /= pnsnd) then (addWeight pnsnd) else id) <$> dfs pnfst pnsnd
else return $ 0
addWeight p = (+) . fromMaybe 0 $ M.lookup p weightedPoints
isPointInBounds :: Point -> Point -> Bool
isPointInBounds (x, y) (bx, by) = x > 0 && x <= bx && y > 0 && y <= by