fork download
  1. import Data.Array
  2. import Data.Monoid
  3. import Data.Foldable (foldMap)
  4.  
  5. main :: IO ()
  6. main = (print . minTurns) =<< fmap read getLine
  7.  
  8. minTurns :: (Int, Int) -> Int
  9. minTurns x
  10. | x < (0, 0) = -1
  11. let ls = search genBoards goal (uncurry (*) x) [initialBoard x]
  12. in case ls of Nothing -> -1; Just a -> length a - 1
  13.  
  14. data Tile = Tile {painted :: Bool, wet :: Int} deriving (Eq)
  15. data Board = Board {pos :: (Int, Int), tiles :: Array (Int, Int) Tile} deriving (Eq)
  16. type Boards = [Board]
  17.  
  18. initialBoard :: (Int, Int) -> Board
  19. initialBoard x = Board (1, 1) (listArray ((1, 1), x) $ repeat (Tile False 0))
  20.  
  21. goal :: Boards -> Bool
  22. goal [] = False
  23. goal ((Board _ ts):_) = all painted $ elems ts
  24.  
  25. mandist :: (Int, Int) -> (Int, Int) -> Int
  26. mandist (x1, y1) (x2, y2) = abs (x1 - x2) + abs (y1 - y2)
  27.  
  28. genBoards :: Boards -> [Boards]
  29. genBoards [] = []
  30. genBoards n@(b:_) = genBoards' b
  31. where
  32. genBoards' (Board p ts) = [b' : n | b' <- allPaints ++ allSteps ++ [Board p ts']]
  33. where
  34. allPaints :: Boards
  35. allPaints =
  36. [Board p (ts' // [(i, t {painted = True, wet = 5})])
  37. | (i, t) <- assocs ts, mandist p i == 1, not (painted t)]
  38. allSteps :: Boards
  39. allSteps =
  40. [Board i ts'
  41. | (i, t) <- assocs ts, mandist p i == 1, wet t == 0]
  42. ts' = fmap (\t -> t {wet = dry t}) ts
  43. dry t | w <- wet t, w > 0 = w - 1
  44. | otherwise = 0
  45.  
  46. search :: (Eq a) => (a -> [a]) -> (a -> Bool) -> Int -> a -> Maybe a
  47. search f g l x = getFirst $ foldMap (search' ([x])) ([l..] :: [Int])
  48. where
  49. search' (y:ys) d
  50. | d == 0 = mempty
  51. | g y = First $ Just y
  52. search' (f y) (d - 1) <> search' ys d
  53. search' _ _ = mempty
  54.  
Success #stdin #stdout 0.17s 6304KB
stdin
(3,2)
stdout
9