网格道路中的格子状态计算

一、分析

下图包含了由正方形格子组成的道路的全部形态。(没有斜向)

 

单个格子的状态共有6种:

 

 

已知构成道路的格子集合:[(x1,y1),(x2,y2)...(xn,yn)],(x,y)代表格子位置。计算道路上每个格子的状态。(格子坐标系,x右正,y上正)

因为每个格子有4个临边,对格子(x,y)有临边:

 左边 L: (x-1, y)

 上边 T: (x,y+1)

 右边 R: (x+1, y)

 下边 B: (x,y-1)


假设最终格子状态为s。计算过程:

1、设置s=无邻格

2、判断L,如果有格,则s=s + L,否则s不变。(s + L)含义为s增加L方向有邻格

3、按步骤2依次判断T R B。为了方便记,如果对应临边有道路格子,则记为1,没有记为0。对于一个格子描述其临边状态可表示为:_ _ _ _ 

                

State(LTRB):0000                 State(LTRB):1101             State(LTRB):1010          State(LTRB):1011      State(LTRB):1111            State(LTRB):0110

 

由图可见,(2)有4种旋转,(3)有两种,(4)有3种,(6)有4种。

 

二、主要思路

   //按位记录4个方向的邻格状态,有为1,无为0
   const int L = 1 << 0;
   const int T = 1 << 1;
   const int R = 1 << 2;
   const int B = 1 << 3;

   //计算x,y 格子的邻格状态
   int s = 0; // 初始为无邻格
   // 依次检查
   if(IsExist(x-1, y))
       s |= L;
   if(IsExist(x, y+1))
       s |= T;
   if(IsExist(x+1, y))
       s |= R;
   if(IsExist(x, y-1))
       s |= B;
   // 最终s的值可知道在各个方向上的邻格情况

 

三、实现

class Road
{
    //对邻格按左->上->右->下的顺序检查
    const int L = 1 << 0;
    const int T = 1 << 1;
    const int R = 1 << 2;
    const int B = 1 << 3;
    const int NONE = 0;

    // 坐标
    struct Coord
    {
        public int x;
        public int y;
    }

    /// 格子邻居
    struct Neibour
    {
        // 与格子的偏移量
        public int ox;
        public int oy;

        // 标识自己是哪个方向的邻居,左->上->右->下
        public int state;
    }

    // 邻居描述集合
    List<Neibour> _neibourMap = new List<Neibour>()
    {
        // 左
        new Neibour {  ox = -1, oy = 0, state = L },
        // 上
        new Neibour {  ox = 0, oy = 1, state = T },
        // 右
        new Neibour {  ox = 1, oy = 0, state = R },
        // 下
        new Neibour {  ox = 0, oy = -1, state = B }
    };

    int GetState(int x, int y)
    {
        var s = NONE;
        foreach (var neibour in _neibourMap)
        {
            if (IsExist(x + neibour.ox, y + neibour.oy))
                s |= neibour.state;
        }

        return s;
    }

    bool IsExist(int x, int y)
    {
        // TODO:判断是否存在
    }

    /// 格子状态对应的信息
    class StateInfo
    {
        // 比如表现
    }

    // 格子状态描述
    Dictionary<int, StateInfo> _stateInfoConfig = new Dictionary<int, StateInfo>()
    {
        // 单格路
        { NONE, new StateInfo()},
        // 末端
        { L, new StateInfo()},
        { T, new StateInfo()},
        { R, new StateInfo()},
        { B, new StateInfo()},
        // 转角
        { L | T, new StateInfo()},
        { T | R, new StateInfo()},
        { R | B, new StateInfo()},
        { B | L, new StateInfo()},
        // 直路 水平或竖直
        { L | R, new StateInfo()},
        { T | B, new StateInfo()},
        // T字路口
        { L | T | R, new StateInfo()},
        { T | R | B, new StateInfo()},
        { R | B | L, new StateInfo()},
        { B | L | T, new StateInfo()},
        // 十字路口
        { L | T | R | B, new StateInfo()}
    };

    /// 测试
    void Test(Coord[] coords)
    {
        foreach (var coord in coords)
        {
            var s = GetState(coord.x, coord.y);
            var info = _stateInfoConfig[s];
            Print(info);
        }
    }

    private void Print(StateInfo info)
    {
        //TODO:状态信息
    }
}

  

转载于:https://www.cnblogs.com/dongzee/p/9996714.html

地点 A 和彼岸 B 位于一个由 H 行、W 列组成的网格地图上。 求地点 A 移动后能看到 彼岸 B 的最小移动距离。 每个格子要么是道路格子,要么是墙壁格子道路格子可以移动。此外,可以透过道路格子看到对面的格子。 墙壁格子不能移动。此外,不能透过墙壁格子看到对面的格子。 地点 A 和彼岸 B 分别位于不同的道路格子上。 只有当当前所在格子的上下左右方向上有 B,并且和 B 之间没有墙壁格子时,此时才能看到 B。 请计算从地点 A 出发,看到彼岸 B 所需的最小移动次数。每次移动可以向上下左右相邻的道路格子移动一次。此外,不能移动到 H 行、W 列的范围之外。 如果移动之后无法看到彼岸 B,则输出 -1。 输入描述 输入将通过标准输入以以下格式给出: H W s_1 s_2 … s_H 第一行给出表示纵向和横向格子数的整数 H 和 W,以空格分隔。 接下来的 H 行中,第 i 行 (1 ≤ i ≤ H) 给出一个由大写字母 “A”、“B” 以及符号 “.”、"#" 组成的长度为 W 的字符串 s_i。s_i 的第 j 个字符 (1 ≤ j ≤ W) 表示从上往下第 i 行、从左往右第 j 列的格子。“A” 表示该格子有 A,“B” 表示该格子有 B。此外,"." 表示道路格子,"#" 表示墙壁格子。“A” 和 “B” 在输入中各出现一次。 输入总共有 H + 1 行,输入的最后一行末尾有一个换行符。这道题考察什么
最新发布
03-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值