注:本文为半转载文章,原文链接为A_L_A_N的博文 总之比原文充实…
/*
Name: A*
Copyright: CQHFBZ
Author: YJ
Date: 2020/01/26 18:45
Description: 咕咕咕,一个让人咕的寻路算法...
*/
是一个让人咕咕咕的优秀的寻路搜索算法
的中心思路是贪心,,和预估函数
的时间复杂度是出的题能过并不是我懒
此处有一地图:
绿色代表起点(),红色代表终点(),蓝色代表障碍(即不可行的状态),小方格代表一种状态(起点,终点皆为一种状态)
那我们开始搜索c
定义两个列表代表待搜索列表和已搜索列表(映射也行)
1. 将起点加入
2. 寻找起点周围可以到达的格子,将他们加入,并将他们的父节点设为起点
3. 将起点弹出并加入
如图,描有浅绿色的边的格子代表在里面的格子
描有浅蓝色的边的格子代表在里面的格子
我们要比出那个格子最靠谱,接下来,就是A*算法最核心的公式
路人:一个三元一次不等式…
其中,代表的经过方格的预估距离
代表从起点到方格的实际距离
代表从方格到终点的预估距离
注意1:计算出的值得尽量小于而又尽量接近实际距离,这跟一个好的密切相关
如上图,我们为了方便讲解,将横着的一步的距离设为,斜着的一步的距离设为,且斜走时旁边不能有障碍我不会告诉你我是为了抠图…
每个已遍历方格的左下角是,右下角是,左上角是
4. 可见值最小的是起点的左边方格,将周围可到达的格子(除障碍物与在内的格子)加入…
停!
我们这时候就要来分类讨论了:
4.1. 某方格已经在里面了
这时候我们就要与前面的值作比较,取最小的值,更新路径(即父节点)
4.2. 某方格还不在里面了
那还不加入…
如上图,那方格的上面方格来讲,他的新值是,而原值是,所以要保留原来路径,不要绕路
5. 现在我们开始寻找中寻找"最靠谱"的方格,但我们发现上面和下面的F值都是,我们这时候就只能靠运气,随便选一个,就拿下面方格举例,称他为,将的周围顶点如一样做处理
注意2:方格并不是由方格走来的,是由的父节点走来的,这是一个很常见的错误?(顺便说一下,我上一句谈到只因为让读者知道位置,而非表达一个递进关系…)
完成后如图:
看看与你是否想的一样
…
…
(个…)
最后,我们会得到两种结果:
.1. 终点已加入,查找成功
那么就沿着父节点向前搜索,直到起点,再反向输出路径:
.2. 已经为空,查找失败
return -1;
上伪代码(本人第一次写伪代码,写的不好可以揍我可以喷我,但不可以揍我,因为我是练习时长两年半的个人:…):
//A_star伪代码//
//前置芝士: 指针//
/*****定义*****/
struct node {
pair<int, int> pos;
int G, H, F;
int father;//0~7, 从上面开始顺时针标号
} Start, End;
int way[2][8] = {{1, 0}, {1, -1}, {0, -1}, {-1, -1}, ......};
vector<node*> OpenList;
vector<node*> CloseList;
/*****定义*****/
/*****过程*****/
node* InList(list<node*> &L, node* find);//寻找find是否在L里面(有返回指针,没返回NULL)
node* MinF();//找出带有最小F值的node指针
bool CanGo(pair<int, int> posx, int wayi);//判断可不可以到达
int GetG(node* X, int wayi);//求G
int GetH(node* X, node* E);//一个优秀的函数
bool AStar(node* S, node* E) {
S -> G = 0;
S -> H = S -> F = Get_H(S, E);
S -> father = -1;
S加入OpenList;
while (OpenList不为空) {
node* X = MinF();
删除OpenList里面的X;
X加入CloseList;
for (i : 0 ~ 7) {
node* Y = 新的node;
if (一大堆要求 and CanGo(X -> pos, i) and InList(CloseList, Y) == NULL) {
if (Y是E) return 1;
求Y的GHF;
node* InListY = InList(OpenList, Y);
if (InList == NULL) {
Y -> father = i;
Y加入OpenList;
}
else {
if (Y -> G < InListY -> G) {
更改InListY的G, F, father;
}
}
}
}
}
return 0;
}
vector<node*> GetPath(node* S, node* E) {
vector<node*> path;
//读者们请自行思考
return path;
}
/*****过程*****/
/*****main*****/
int main() {
//读者们请自行思考
return 0;
}
489.第k短路
题目描述
给定一张N个点(编号1,2…N),M条边的有向图,求从起点S到终点T的第K短路的长度,路径允许重复经过点或边。
注意:每条最短路中至少要包含一条边。
输入格式
第一行包含两个整数N和M。
接下来M行,每行包含三个整数A,B和L,表示点A与点B之间存在有向边,且边长为L。
最后一行包含三个整数S,T和K,分别表示起点S,终点T和第K短路。
输出格式
输出占一行,包含一个整数,表示第K短路的长度,如果第K短路不存在,则输出“-1”。
样例
样例输入
2 2
1 2 5
2 1 4
1 2 2
样例输出
14
数据范围与提示
1 <= n <= 1000, 0 <= m <= 100000
1 <= a, b <= N, 1 <= T(权值)<= 100
1 <= s, t <= N, 1 <= k <= 1000
由于路径可以重复,所以统统不要,函数就是由终点道各点的路径(即可)
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;
template <typename T>
inline void read(T &x) {
x = 0;
T ff = 1, ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
ff = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= ff;
}
template <typename T>
inline void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int n, m, s, t, k;
int f[MAXN], vis[MAXN];
int lin[MAXN], tot = 0, linc[MAXN], totc = 0;
struct edge {
int y, v, next;
} a[MAXN], e[MAXN];
struct node {
int pos, H, G;
bool operator < (node a) const { return a.H + a.G < H + G; }
};
inline void add(int xx, int yy, int vv) {
a[++tot].y = yy;
a[tot].v = vv;
a[tot].next = lin[xx];
lin[xx] = tot;
}
inline void addc(int xx, int yy, int vv) {
e[++totc].y = yy;
e[totc].v = vv;
e[totc].next = linc[xx];
linc[xx] = totc;
}
void SPFA() {
queue<int> q;
memset(f, 0x3f, sizeof(f));
memset(vis, false, sizeof(vis));
q.push(t);
f[t] = 0;
vis[t] = true;
while (!q.empty()) {
int x = q.front();
q.pop();
vis[x] = false;
for (int i = lin[x], y; i; i = a[i].next) {
if (f[y = a[i].y] > f[x] + a[i].v) {
f[y] = f[x] + a[i].v;
if (!vis[y]) {
vis[y] = true;
q.push(y);
}
}
}
}
}
int astar() {
priority_queue<node> q;
if (f[s] == INF)
return -1;
int ts[MAXN];
node tmp, h;
h.pos = s;
h.H = 0;
h.G = 0;
q.push(h);
while (!q.empty()) {
node x = q.top();
q.pop();
ts[x.pos]++;
if (ts[x.pos] == k && x.pos == t)
return x.G;
if (ts[x.pos] > k)
continue;
for (int i = linc[x.pos]; i; i = e[i].next) {
tmp.pos = e[i].y;
tmp.H = f[e[i].y];
tmp.G = x.G + e[i].v;
q.push(tmp);
}
}
return -1;
}
int main() {
read(n);
read(m);
for (int i = 1; i <= m; ++i) {
int u, v, w;
read(u);
read(v);
read(w);
add(v, u, w);
addc(u, v, w);
}
read(s);
read(t);
read(k);
if (s == t)
++k;
SPFA();
write(astar());
return 0;
}
来源:CSDN
作者:樱花滴温柔
链接:https://blog.csdn.net/qq_44598375/article/details/104210450

