AtCoder Beginner Contest 311 D

https://atcoder.jp/contests/abc311/tasks/abc311_d

進める方向すべてに進めばいいだけですね。

// Grid Ice Floor
#![allow(non_snake_case)]

use std::collections::BTreeSet;


//////////////////// library ////////////////////

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}


//////////////////// Maze ////////////////////

type Point = (usize, usize);
type Maze = Vec<Vec<bool>>;

fn is_ice(point: &Point, maze: &Maze) -> bool {
    point.0 < maze.len() && point.1 < maze[0].len() && maze[point.0][point.1]
}

fn step(dir: i32, point: &Point) -> Point {
    match dir {
        0 => (point.0 + 1, point.1),
        1 => (point.0,     point.1 + 1),
        2 => (point.0 - 1, point.1),
        _ => (point.0,     point.1 - 1)
    }
}

fn possible_dirs(point: &Point, maze: &Maze) -> Vec<i32> {
    (0..4).filter(|dir| is_ice(&step(*dir, point), maze)).collect::<Vec<i32>>()
}

fn read_maze() -> Maze {
    let v: Vec<usize> = read_vec();
    let N = v[0];
    let S: Vec<String> = (0..N).map(|_| read()).collect();
    S.into_iter().
            map(|s| s.chars().map(|c| c == '.').collect::<Vec<bool>>()).
                                                        collect::<Maze>()
}


//////////////////// process ////////////////////

fn slide(start: &Point, dir: i32, maze: &Maze) -> Vec<Point> {
    let mut points: Vec<Point> = Vec::new();
    let mut pt = *start;
    loop {
        pt = step(dir, &pt);
        if !is_ice(&pt, maze) {
            break
        }
        points.push(pt)
    }
    points
}

fn f(maze: Maze) -> usize {
    let mut stack: Vec<Point> = vec![(1, 1)];
    let mut visited: BTreeSet<Point> = BTreeSet::new();
    visited.insert((1, 1));
    while let Some(point) = stack.pop() {
        let dirs = possible_dirs(&point, &maze);
        for dir in dirs.into_iter() {
            let points = slide(&point, dir, &maze);
            let next_point = *points.last().unwrap();
            if !visited.contains(&next_point) {
                stack.push(next_point)
            }
            visited.extend(points.into_iter())
        }
    }
    visited.len()
}


//////////////////// main ////////////////////

fn main() {
    let maze = read_maze();
    println!("{}", f(maze));
}