dijstra算法
应用场景
从原点出发,从图上的边到达另一个点所经过的路径中,各边上权值之和最小的路径称为最短路径。
算法过程
/**
从原点0到目标点1的最短距离
算法思想:类似prim算法,定义一个一维数组(path)存储V0到某个点的最短距离
*/
int shortestPathDijStra(int N)
{
//1、path 数组初始化,如果找到比原来更短的则直接覆盖
memcpy(path, matrix[0], MAX_SIZE);
visit[0] = true;
for (int i=1;i<N;i++)
{
//2、在已经存在的路径中找到一条最短的且未被访问的路径节点
int minDis = INF;
int minIndex = -1;
for (int j=1;j<=N;j++)
{
if (!visit[j] && minDis > path[j])
{
minDis = path[j];
minIndex = j;
}
}
if (minIndex== -1)
break;
visit[minIndex] = true;
//3、在未被访问的路径节点中,判断是否比现在已经存在的最短路径短,是则进行覆盖
for (int j=1;j<=N;j++)
{
if (!visit[j] && path[j] > (minDis + matrix[minIndex][j]))
{
path[j] = minDis + matrix[minIndex][j];
}
}
}
return path[1];
}
oj
A star 算法
应用场景
A* 搜索是静态路网中求解最短路径的最有效的直接搜索方式。算法中的估算函数与实际距离越接近,最终搜索速度最快。
A* 搜索与Dijstra的不同之处在于A*是一种“启发式”搜索,它有一些我们告诉它的先验知识,对BFS的顺序进行了调整,少搜索了那些不太可能经过的点,从而能更快找到目标点的最短距离。
关于估值函数的总结
启发函数:
F = G + H
G:从起始点到当前点的实际移动代价
H:从当前点到目标点的估算成本
G来源于已知信息,H为未知信息的估算,F为选择下一个节点进行遍历的依据。
关于H的特性:
- 在极端情况下,H 为0,则算法退化为Dijstra算法
- H小于等于实际距离,一定能找到最短距离,H值越小,将遍历的节点越多
证明:*定义d为实际距离,g + d (最优搜索路径) < g + d (非最优搜索距离), 若 H < d,则不会存在一种情况,使(最优搜索路径的)g + h > (非最优搜索的)g + d。随着深度的不断增加,g + h 会不断趋向 g + d。*在一个非最优解的路径中,随着深度增大,一定会在某一层,出现最优解估值大的情况,所以最先搜索到的就是最优解。 - H大于实际距离,不保证找到最短距离,但此时算法会很快
算法过程
const int MAX_SIZE = 105;
int mp[MAX_SIZE*MAX_SIZE];
struct Knight
{
int f, g, h;
int x, y;
bool operator < (const Knight b) const
{
return f > b.f;
}
Knight(int F, int G, int H)
{
f = F;
g = G;
h = H;
}
};
//1、定义开放列表
priority_queue<Knight> openList;
int scol, srow, ecol, erow;
int dir[][2] = {{1,-2},{1,2},{-1,-2},{-1,2},{2,-1},{2,1},{-2,-1},{-2,1}};
bool isValid(int x, int y)
{
return x>=0&&x<8&&y>=1&&y<=8;
}
//启发函数
int heuristic(int x, int y)
{
return max(abs(x - ecol), abs(y - erow))/2;
}
/**3、重复如下工作:
a)寻找开放列表中F值最低的点
b)把它切换到关闭列表(标记)
c)遍历它相邻的每一个点
*/
int Astar()
{
while(!openList.empty())
{
Knight top = openList.top();
openList.pop();
if (top.x == ecol && top.y == erow)
{
return top.g;
}
mp[top.x*MAX_SIZE + top.y] = 1;
for (int i=0; i<8; i++)
{
int x = dir[i][0] + top.x;
int y = dir[i][1] + top.y;
if (isValid(x, y) && mp[x*MAX_SIZE + y] == 0)
{
int h = heuristic(x, y);
int g = top.g + 1;
int f = g + h;
Knight p(f, g, h);
p.x = x;
p.y = y;
openList.push(p);
}
}
}
return -1;
}
int main()
{
char from[20], to[20];
while(scanf("%s", from) != EOF)
{
scanf("%s", to);
scol = from[0] - 'a';
srow = from[1] - '0';
ecol = to[0] - 'a';
erow = to[1] - '0';
int h = heuristic(scol,srow);
int g = 0;
int f = g + h;
Knight start(f, g, h);
start.x = scol;
start.y = srow;
while(!openList.empty())
openList.pop();
memset(mp, 0, sizeof(int)*MAX_SIZE*MAX_SIZE);
//2、将起始点加入开放列表
openList.push(start);
cout<<Astar()<<endl;
}
return 0;
}
oj
Knight Moves最短路径-从dijstra到导航网格
dijstra算法
应用场景
从原点出发,从图上的边到达另一个点所经过的路径中,各边上权值之和最小的路径称为最短路径。
算法过程
/**
从原点0到目标点1的最短距离
算法思想:类似prim算法,定义一个一维数组(path)存储V0到某个点的最短距离
*/
int shortestPathDijStra(int N)
{
//1、path 数组初始化,如果找到比原来更短的则直接覆盖
memcpy(path, matrix[0], MAX_SIZE);
visit[0] = true;
for (int i=1;i<N;i++)
{
//2、在已经存在的路径中找到一条最短的且未被访问的路径节点
int minDis = INF;
int minIndex = -1;
for (int j=1;j<=N;j++)
{
if (!visit[j] && minDis > path[j])
{
minDis = path[j];
minIndex = j;
}
}
if (minIndex== -1)
break;
visit[minIndex] = true;
//3、在未被访问的路径节点中,判断是否比现在已经存在的最短路径短,是则进行覆盖
for (int j=1;j<=N;j++)
{
if (!visit[j] && path[j] > (minDis + matrix[minIndex][j]))
{
path[j] = minDis + matrix[minIndex][j];
}
}
}
return path[1];
}
oj
A star 算法
应用场景
A* 搜索是静态路网中求解最短路径的最有效的直接搜索方式。算法中的估算函数与实际距离越接近,最终搜索速度最快。
A* 搜索与Dijstra的不同之处在于A*是一种“启发式”搜索,它有一些我们告诉它的先验知识,对BFS的顺序进行了调整,少搜索了那些不太可能经过的点,从而能更快找到目标点的最短距离。
关于估值函数的总结
启发函数:
F = G + H
G:从起始点到当前点的实际移动代价
H:从当前点到目标点的估算成本
G来源于已知信息,H为未知信息的估算,F为选择下一个节点进行遍历的依据。
关于H的特性:
- 在极端情况下,H 为0,则算法退化为Dijstra算法
- H小于等于实际距离,一定能找到最短距离,H值越小,将遍历的节点越多
证明:*定义d为实际距离,g + d (最优搜索路径) < g + d (非最优搜索距离), 若 H < d,则不会存在一种情况,使(最优搜索路径的)g + h > (非最优搜索的)g + d。随着深度的不断增加,g + h 会不断趋向 g + d。*在一个非最优解的路径中,随着深度增大,一定会在某一层,出现最优解估值大的情况,所以最先搜索到的就是最优解。 - H大于实际距离,不保证找到最短距离,但此时算法会很快
算法过程
const int MAX_SIZE = 105;
int mp[MAX_SIZE*MAX_SIZE];
struct Knight
{
int f, g, h;
int x, y;
bool operator < (const Knight b) const
{
return f > b.f;
}
Knight(int F, int G, int H)
{
f = F;
g = G;
h = H;
}
};
//1、定义开放列表
priority_queue<Knight> openList;
int scol, srow, ecol, erow;
int dir[][2] = {{1,-2},{1,2},{-1,-2},{-1,2},{2,-1},{2,1},{-2,-1},{-2,1}};
bool isValid(int x, int y)
{
return x>=0&&x<8&&y>=1&&y<=8;
}
//启发函数
int heuristic(int x, int y)
{
return max(abs(x - ecol), abs(y - erow))/2;
}
/**3、重复如下工作:
a)寻找开放列表中F值最低的点
b)把它切换到关闭列表(标记)
c)遍历它相邻的每一个点
*/
int Astar()
{
while(!openList.empty())
{
Knight top = openList.top();
openList.pop();
if (top.x == ecol && top.y == erow)
{
return top.g;
}
mp[top.x*MAX_SIZE + top.y] = 1;
for (int i=0; i<8; i++)
{
int x = dir[i][0] + top.x;
int y = dir[i][1] + top.y;
if (isValid(x, y) && mp[x*MAX_SIZE + y] == 0)
{
int h = heuristic(x, y);
int g = top.g + 1;
int f = g + h;
Knight p(f, g, h);
p.x = x;
p.y = y;
openList.push(p);
}
}
}
return -1;
}
int main()
{
char from[20], to[20];
while(scanf("%s", from) != EOF)
{
scanf("%s", to);
scol = from[0] - 'a';
srow = from[1] - '0';
ecol = to[0] - 'a';
erow = to[1] - '0';
int h = heuristic(scol,srow);
int g = 0;
int f = g + h;
Knight start(f, g, h);
start.x = scol;
start.y = srow;
while(!openList.empty())
openList.pop();
memset(mp, 0, sizeof(int)*MAX_SIZE*MAX_SIZE);
//2、将起始点加入开放列表
openList.push(start);
cout<<Astar()<<endl;
}
return 0;
}