关于c# 消防逃生,多入口多出口算法。

最近弄一个消防逃生系统,需要实现 如下图功能,人处于道路上任意一个地址,都指示出通往最近出口的方向。那个算法大师,能告诉我我这个算法能优化吗?同时现在这个算法比较正式的名字叫啥算法?

算法思路:

      

算法实现如下:

一、定点格子对象

/// <summary>
/// 点的对象
/// </summary>
public class Cell
{
    public int X { get; private set; }
    public int Y { get; private set; }
    /// <summary>
    /// 格子类型
    /// </summary>
    public TileType TileType { get; set; }
    /// <summary>
    /// 箭头方向
    /// </summary>
    public Direction Direction { get; set; }
    /// <summary>
    /// 离最近终点步数
    /// </summary>
    public int ToExitStepNumber { get; set; }
    /// <summary>
    /// 最近终点
    /// </summary>
    public Cell ExitCell { get; set; }
    /// <summary>
    /// 上级格子
    /// </summary>
    public Cell ParentCell { get; set; }

    public Cell(int x, int y)
    {
        X = x;
        Y = y;
    }

    public static bool operator ==(Cell a, Cell b)
    {
        if (ReferenceEquals(a, b))
        {
            return true;
        }

        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }
        return a.X == b.X && a.Y == b.Y;
    }

    public static bool operator !=(Cell a, Cell b) => !(a == b);

    public override bool Equals(object obj) => (this == (Cell)obj);

    public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode();
}


public enum TileType
{
    /// <summary>
    /// 无状态
    /// </summary>
    Non = 0,
    /// <summary>
    ////// </summary>
    Wall,
    /// <summary>
    ////// </summary>
    Road,
    /// <summary>
    /// 出口
    /// </summary>
    Exit,
    /// <summary>
    /// 障碍物
    /// </summary>
    Obstacle,
    /// <summary>
    /// 临时
    /// </summary>
    Temp
}

/// <summary>
/// 行进方向
/// </summary>
public enum Direction
{
    /// <summary>
    /// 无路
    /// </summary>
    Non,
    /// <summary>
    ////// </summary>
    Left,
    /// <summary>
    ////// </summary>
    Top,
    /// <summary>
    ////// </summary>
    Right,
    /// <summary>
    ////// </summary>
    Botton
}

二、最后实现算法

public class EscapeUtils
{
    /// <summary>
    /// 逃生工具
    /// </summary>
    /// <param name="matrix">当前迷宫的数据化矩阵</param>
    public EscapeUtils(Cell[][] matrix)
    {
        this.Matrix = matrix;
        this.RowCount = matrix[0].Length;
        this.ColCount = matrix.Length;
    }

    /// <summary>
    /// 找路
    /// </summary>
    public void FindRoad()
    {
        var exits = new List<Cell>(); // 存放出口的集合

        foreach (var rows in Matrix)  // 遍历所有点,并初始化路径。和找出出口的点
        {
            foreach (var cell in rows)
            {
                cell.Direction = Direction.Non;
                cell.ToExitStepNumber = 0;
                cell.ExitCell = null;

                if (cell.TileType == TileType.Exit)
                {
                    exits.Add(cell);
                }
            }
        }
        foreach (var exit in exits)  //遍历所有出口
        {
            List<Cell> list = new List<Cell>();   // 声明一个集合存放已找到的点
            int num = 0;
            list.Add(exit);                       // 将当前出口放入集合中
            do
            {
                var nowCell = list[num];
                var cs = GetNeighbors(nowCell, exit);    // 找到当前点能去的所有地址
                if (cs != null && cs.Count() > 0)
                {
                    list.AddRange(cs);      // 将找到的新的地址放入已找到的集合中
                }
                num++;
            }
            while (num <= (list.Count - 1));      // 直到找不到新的可去的地址
        }
    }


    public int ColCount { get; set; }

    public int RowCount { get; set; }
    /// <summary>
    /// 数据矩阵
    /// </summary>
    public Cell[][] Matrix { get; set; }

    private static readonly float[,] neighbors = new float[,]
    {
       { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 }
    };

    /// <summary>
    /// 寻找当前点周围的点到指定终点
    /// </summary>
    /// <param name="nowCell">当前节点</param>
    /// <param name="exit">指定终点</param>
    /// <returns></returns>
    public IEnumerable<Cell> GetNeighbors(Cell nowCell, Cell exit)
    {
        var result = new List<Cell>();

        for (var i = 0; i < neighbors.GetLongLength(0); i++)
        {
            var x = nowCell.X + neighbors[i, 0];
            var y = nowCell.Y + neighbors[i, 1];
            if (x >= 0 && y >= 0 && x < ColCount && y < RowCount)
            {
                // 找到上下左右的一个点
                var nextCell = Matrix[(int)x][(int)y];

                // 判断该点是否需要更新,不需更新代表不通行 必须是路,且该点没有关联出口或者新的出口距离更短
                if (nextCell.TileType == TileType.Road && (nextCell.ExitCell == null || nextCell.ToExitStepNumber > nowCell.ToExitStepNumber + 1))
                {
                    nextCell.ExitCell = exit;
                    nextCell.ToExitStepNumber = nowCell.ToExitStepNumber + 1;
                    nextCell.ParentCell = nowCell;
                    // 比较相邻两个点,求出方向
                    if (nextCell.X == nowCell.X)
                    {
                        if (nextCell.Y > nowCell.Y)
                        {
                            nextCell.Direction = Direction.Top;
                        }
                        else
                        {
                            nextCell.Direction = Direction.Botton;
                        }
                    }
                    else if (nextCell.Y == nowCell.Y)
                    {
                        if (nextCell.X < nowCell.X)
                        {
                            nextCell.Direction = Direction.Right;
                        }
                        else
                        {
                            nextCell.Direction = Direction.Left;
                        }
                    }
                    result.Add(nextCell);
                }
            }
        }
        return result;
    }
}

总结:该算法的消耗,第一个终点会便利所有的路,第二个则会是1/2的点,第三个则是 1/3的点 ····。

最后遍历的总数为  设 路的格子数为 x,出口的格子数为 y ,总遍历数为 z。 那么

 z = (1+1/2+1/3+1/4+…+1/y)x 。

 可以得到全部路的前进方向。

猜你喜欢

转载自www.cnblogs.com/lscb/p/9030555.html
今日推荐