TopCoder SRM 440 Div1 Medium in F#

F#で書いた。工夫した点?知りませんなぁ。

let maze = [".........";  "XXX.XXXX.";  ".XX.X....";  ".....XX.X"]
let sx, sy = 0, 0
let dx, dy = [1; -1; 0; 0], [0; 0; 1; -1]
let N, M = List.length maze, maze.[0].Length
let ex = Array2.init N M (fun _ _ -> 0.0)

let rec dfs1 x y px py =
    let l =
        [for i in 0..3 ->
            let nx = x + dx.[i]
            let ny = y + dy.[i]
            if (nx <> px || ny <> py) &&
               nx >= 0 && ny >= 0 && nx < M && ny < N &&
               maze.[ny].[nx] <> 'X' then
                dfs1 nx ny x y;
                ex.[ny, nx] + 1.0
            else 0.0]
    in ex.[y, x] <- 1.0 + List.fold_left (+) 0.0 l

let exsum = ref 0.0

let rec dfs2 x y px py sum =
    let nsum = sum + ex.[y, x]
    exsum := !exsum + nsum;
    [for i in 0..3 ->
        let nx = x + dx.[i]
        let ny = y + dy.[i]
        if (nx <> px || ny <> py) &&
           nx >= 0 && ny >= 0 && nx < M && ny < N &&
           maze.[ny].[nx] <> 'X' then
            dfs2 nx ny x y nsum] |> ignore

let rec count s c n =
    match s with
    | [] -> n
    | x::xs ->
        if x = c then count xs c (n + 1)
        else count xs c n

let expectedTime () =
    dfs1 sx sy -1 -1;
    dfs2 sx sy -1 -1 -ex.[sy, sx];
    let ct = List.fold_left (+) 0
                [for i in 0..N-1 -> count [for c in maze.[i] -> c] '.' 0]
    in !exsum / float ct

実行結果↓

> expectedTime ();;
val it : float = 167.2608696