Life Goes On

まあまあだけど楽しんでる方です

レイトン教授ってなによ?

id:matarillo さんが、ここ とか ここ で書いている問題を解いてみました。
基本的には枝刈りありの全数探索。
c から c' までノードを一つ一つ辿りながら、a から a' までのルートと、b から b' までのルートが残っているかを都度確かめていきます。どちらかのルートが途切れたら、探索打ち切り。
この枝刈りが強力で、実行は一瞬でした。
もう一つのポイントは探索するルートとして cc' を選んだことです。
ルート aa' とかを探索した場合、ルート bb' や cc' が個別に成り立ったとしても、同時に成り立つかは分からないので、もう一度探索しなくてはなりません。
それに対してルート cc' はルート aa' と bb' の“間に”あって、ちょっとでもブレると aa' か bb' のどちらかが途切れてしまうので、解を一気に絞り込めます。(答えを知ってからやってるのでちょっとズルい気もしますが)

import Data.List

type Vertex = Int
type Graph = [[Vertex]]

main = print $ search graph 17

graph :: Graph
graph = [[0,1],[0,10],[0,21],[1,2],[1,28],[2,3],[2,6],[3,4],[4,5],[4,8],[5,6],
    [5,7],[6,11],[7,14],[8,9],[8,10],[9,16],[10,29],[11,14],[11,28],[12,13],[12,20],
    [12,27],[13,14],[13,19],[15,16],[15,18],[15,29],[16,17],[17,18],[18,26],[19,22],
    [19,28],[20,22],[20,25],[21,24],[21,29],[22,23],[23,24],[24,25],[25,26],[26,27]]

search :: Graph -> Vertex -> [[Vertex]]
search es 7 = [[7]]
search es c = map (c :) $ concat [ search es' c' |
    let (e, es') = partition (elem c) es,
    connected es' 23 9,
    connected es' 27 3,
    c' <- filter (/= c) $ concat e ]

connected :: Graph -> Vertex -> Vertex -> Bool
connected es v0 v1 = any (elem v1) $ unfoldr phi (es, [v0])
    where
    phi (es, vs) = if null e then Nothing else Just (vs',(es',vs'))
        where
        (e, es') = partition (any (flip elem vs)) es
        vs' = concat e \\ vs
c:\Haskell>runghc mata.hs
[[17,18,26,25,20,22,19,28,1,0,10,8,4,5,7]]