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