Algorithm 到达目的地要走多少步?有效填洪

Algorithm 到达目的地要走多少步?有效填洪,algorithm,fill,Algorithm,Fill,我想计算细胞到目标细胞的距离,使用四向运动的次数来达到某个目标。因此,与目的地相邻的四个单元格的距离为1,每个单元格的四个基本方向上的单元格的距离为2,依此类推。有一个最大距离,可能是16或20左右,并且有细胞被屏障占据;距离可以绕着它们流动,但不能穿过它们 我希望将输出存储到2D数组中,并且我希望能够非常快速地计算出迷宫地图上任何目的地的“距离地图” 我成功地用一个变化来填充一个充斥的填充单元,在一个优先队列中(用C++ STL),它的增量距离。 我对这个功能很满意,现在想把重点放在优化代码上

我想计算细胞到目标细胞的距离,使用四向运动的次数来达到某个目标。因此,与目的地相邻的四个单元格的距离为1,每个单元格的四个基本方向上的单元格的距离为2,依此类推。有一个最大距离,可能是16或20左右,并且有细胞被屏障占据;距离可以绕着它们流动,但不能穿过它们

我希望将输出存储到2D数组中,并且我希望能够非常快速地计算出迷宫地图上任何目的地的“距离地图”

我成功地用一个变化来填充一个充斥的填充单元,在一个优先队列中(用C++ STL),它的增量距离。 我对这个功能很满意,现在想把重点放在优化代码上,因为它对性能非常敏感

可能会有什么狡猾和快速的方法?


我认为你做的每件事都是对的。如果编码正确,则需要O(n)时间和O(n)内存来计算泛洪填充,其中n是单元数,可以证明不可能做得更好(一般情况下)。填充完成后,您只需使用O(1)返回任何目的地的距离,很容易看出它也可以做得更好

因此,如果您想要优化性能,您只能专注于代码局部优化。这不会影响渐进,但可以显著提高您的实际执行时间。但是,在没有看到源代码的情况下,很难为代码优化提供任何建议

因此,如果您真的想看到优化的代码,请参见以下内容(纯C):

包括
int*BFS()
{
int N,M;//假设我们有NxM网格。
int X,Y;//起始位置。X,Y基于单位。
int i,j;
int movex[4]={0,0,1,-1};//在x维度上移动。
int movey[4]={1,-1,0,0};//在y维度上移动。
//要做的事情:读N,M,X,Y
//减少冗余函数调用和内存重新分配
//一次分配所有需要的内存并使用简单的数组。
int*map=(int*)malloc((N+2)*(M+2));
int-leadDim=M+2;
//我们的地图。我们使用一维数组。地图[x][y]=map[leadDim*x+y];
//如果(x,y)被占用,则map[leadDim*x+y]=-1;
//如果(x,y)未访问,则映射[leadDim*x+y]=-2;
int*队列=(int*)malloc(N*M);
int first=0,last=1;
//填充寄宿生以简化代码并减少条件
对于(i=0;i

代码可能看起来很棘手。当然,它看起来不像OOP(我真的认为OOP的粉丝们会讨厌它),但是如果你想要快速的东西,那就是你所需要的

从递归实现开始:(未测试的代码)

int访问(int xy,int dist){
int-ret=1;
if(array[xy]这是的常见任务。复杂性是O(cellsunt)

我的C++实现:

vector<vector<int> > GetDistance(int x, int y, vector<vector<int> > cells)
{
    const int INF = 0x7FFFFF;
    vector<vector<int> > distance(cells.size());
    for(int i = 0; i < distance.size(); i++)
        distance[i].assign(cells[i].size(), INF);
    queue<pair<int, int> > q;

    q.push(make_pair(x, y));
    distance[x][y] = 0;

    while(!q.empty())
    {
        pair<int, int> curPoint = q.front();
        q.pop();
        int curDistance = distance[curPoint.first][curPoint.second];
        for(int i = -1; i <= 1; i++)
            for(int j = -1; j <= 1; j++)
            {
                if( (i + j) % 2 == 0 ) continue;
                pair<int, int> nextPoint(curPoint.first + i, curPoint.second + j);
                if(nextPoint.first >= 0 && nextPoint.first < cells.size()
                   && nextPoint.second >= 0 && nextPoint.second < cells[nextPoint.first].size()
                   && cells[nextPoint.first][nextPoint.second] != BARRIER
                   && distance[nextPoint.first][nextPoint.second] > curDistance + 1)
                   {
                       distance[nextPoint.first][nextPoint.second] = curDistance + 1;
                       q.push(nextPoint);
                   }                    
            }
    }
    return distance;
}
向量GetDistance(int x,int y,向量单元格) { 常量int INF=0x7FFFFF; 向量距离(cells.size()); 对于(int i=0;icurDistance+1) { 距离[nextPoint.first][nextPoint.second]=curDistance+1; q、 推(下一点); } } } 返回距离; }
20世纪70年代的8位计算机通过一种优化实现了这一点,这种优化具有相同的算法复杂性,但在典型情况下,在实际硬件上要快得多

从初始正方形开始,向左和向右扫描,直到找到“墙”。现在您有一个“跨度”,即一个正方形高,N个正方形宽。将跨度标记为“填充”,在本例中,每个正方形与初始正方形的距离相同

对于当前跨度上方和下方的每个正方形,如果它不是“墙”或已填充,请将其作为跨度的新原点

重复此操作,直到找不到新跨距

由于水平行倾向于连续存储在内存中,因此该算法对缓存的抖动远小于对水平搜索没有偏见的算法


此外,由于在最常见的情况下,从堆栈中推送和弹出的项目要少得多(跨度而不是单个块)维护堆栈所花费的时间更少。

如果没有代码,很难知道什么可以优化…您可以使用简单的
队列
而不是
优先级队列
,因为您按照与起始单元格的距离的递增顺序迭代单元格。优先级队列不是O(1)?我希望得到关于行进或清扫算法的描述。有很多p
 int visit( int xy, int dist) {
    int ret =1;
    if (array[xy] <= dist) return 0;
    array[xy] = dist;
    if (dist == maxdist) return ret;
    ret += visit ( RIGHT(xy) , dist+1);
    ... 
    same for left, up, down
    ...
    return ret;
    }
vector<vector<int> > GetDistance(int x, int y, vector<vector<int> > cells)
{
    const int INF = 0x7FFFFF;
    vector<vector<int> > distance(cells.size());
    for(int i = 0; i < distance.size(); i++)
        distance[i].assign(cells[i].size(), INF);
    queue<pair<int, int> > q;

    q.push(make_pair(x, y));
    distance[x][y] = 0;

    while(!q.empty())
    {
        pair<int, int> curPoint = q.front();
        q.pop();
        int curDistance = distance[curPoint.first][curPoint.second];
        for(int i = -1; i <= 1; i++)
            for(int j = -1; j <= 1; j++)
            {
                if( (i + j) % 2 == 0 ) continue;
                pair<int, int> nextPoint(curPoint.first + i, curPoint.second + j);
                if(nextPoint.first >= 0 && nextPoint.first < cells.size()
                   && nextPoint.second >= 0 && nextPoint.second < cells[nextPoint.first].size()
                   && cells[nextPoint.first][nextPoint.second] != BARRIER
                   && distance[nextPoint.first][nextPoint.second] > curDistance + 1)
                   {
                       distance[nextPoint.first][nextPoint.second] = curDistance + 1;
                       q.push(nextPoint);
                   }                    
            }
    }
    return distance;
}