Problem 244
コンテンツ
244 Sliders
15 puzzle が2色に塗り分けられたときの話.
最短手順ではなく,全ての最短手順を求めなくてはいけないのだが…
状態数は高々 16*2^16 = 1,048,576 なので,全探索できるレベル.
なので,適当にコードをつくった.
はじめは,Lは空白を左に動かす操作だと思っていた.正しくは,空白の右隣のピースを左に動かす操作である.
これで,一瞬ハマリかけた.
import Data.Char (ord) import Data.Array.Unboxed (UArray ,listArray, range, (//), (!)) import Data.Maybe (mapMaybe) import Data.Map (toList, fromListWith) type Board = ((Int, Int), UArray (Int, Int) Bool) type State = (Board, [Integer]) start, goal :: Board start = ((1,1), listArray ((1,1), (4,4)).cycle $ [False, False, True, True]) goal = ((1,1), listArray ((1,1), (4,4)).cycle $ [False, True, False, True, True, False, True, False]) move :: State -> Char -> Maybe State move ( ((x,y), b), css ) c | not.elem (x + dx, y + dy).range $ ((1,1),(4,4)) = Nothing | otherwise = Just ( ((x + dx,y + dy), b //[ ((x,y), a), ((x + dx,y + dy), False) ] ), map (updateCS c) css ) where a = b ! (x + dx, y + dy) dx | c == 'U' = 1 | c == 'D' = -1 | otherwise = dy | c == 'L' = 1 | c == 'R' = -1 | otherwise = updateCS :: Char -> Integer -> Integer updateCS c cs = mod (cs*243 + toInteger (ord c)) 100000007 step :: [State] -> [State] step ss = toList.fromListWith (++).concatMap next $ ss where next s = mapMaybe (move s) $ "LRUD" main :: IO () main = print.sum.snd.head.filter ((==goal).fst).(!!32).iterate step $ [(start, [])]
ものすごい,そのままの幅優先探索である.
作成者 Toru Mano
最終更新時刻 2023-01-01 (c70d5a1)