A*
A*算法是BFS的一种改进。
定义起点
从起点(初始状态)开始的距离函数
到终点(最终状态)的距离函数
定义每个点的估价函数
A*算法每次从 优先队列 中取出一个
如果
上述条件下,如果
其实……
例题八数码¶
题目大意:在
1 2 3 | 123 804 765 |
),找到一种从初始布局到目标布局最少步骤的移动方法。
容易发现
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <algorithm> #include <cstdio> #include <cstring> #include <queue> #include <set> using namespace std; const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1}; int fx, fy; char ch; struct matrix { int a[5][5]; bool operator<(matrix x) const { for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) if (a[i][j] != x.a[i][j]) return a[i][j] < x.a[i][j]; return false; } } f, st; int h(matrix a) { int ret = 0; for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) if (a.a[i][j] != st.a[i][j]) ret++; return ret; } struct node { matrix a; int t; bool operator<(node x) const { return t + h(a) > x.t + h(x.a); } } x; priority_queue<node> q; set<matrix> s; int main() { st.a[1][1] = 1; st.a[1][2] = 2; st.a[1][3] = 3; st.a[2][1] = 8; st.a[2][2] = 0; st.a[2][3] = 4; st.a[3][1] = 7; st.a[3][2] = 6; st.a[3][3] = 5; for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) { scanf(" %c", &ch); f.a[i][j] = ch - '0'; } q.push({f, 0}); while (!q.empty()) { x = q.top(); q.pop(); if (!h(x.a)) { printf("%d\n", x.t); return 0; } for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) if (!x.a.a[i][j]) fx = i, fy = j; for (int i = 0; i < 4; i++) { int xx = fx + dx[i], yy = fy + dy[i]; if (1 <= xx && xx <= 3 && 1 <= yy && yy <= 3) { swap(x.a.a[fx][fy], x.a.a[xx][yy]); if (!s.count(x.a)) s.insert(x.a), q.push({x.a, x.t + 1}); swap(x.a.a[fx][fy], x.a.a[xx][yy]); } } } return 0; } |
例题k 短路¶
题目大意:按顺序求一个有向图上从结点
很容易发现,这个问题很容易转化成用 A*算法解决问题的标准程式。
初始状态为处于结点
就这样,我们在预处理的时候反向建图,计算出结点
由于设计的距离函数和估价函数,每个状态需要存储两个参数,当前结点
我们可以在此基础上加一点小优化:由于只需要求出第
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #include <algorithm> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int maxn = 5010; const int maxm = 400010; const double inf = 2e9; int n, m, k, u, v, cur, h[maxn], nxt[maxm], p[maxm], cnt[maxn], ans; int cur1, h1[maxn], nxt1[maxm], p1[maxm]; double e, ww, w[maxm], f[maxn]; double w1[maxm]; bool tf[maxn]; void add_edge(int x, int y, double z) { cur++; nxt[cur] = h[x]; h[x] = cur; p[cur] = y; w[cur] = z; } void add_edge1(int x, int y, double z) { cur1++; nxt1[cur1] = h1[x]; h1[x] = cur1; p1[cur1] = y; w1[cur1] = z; } struct node { int x; double v; bool operator<(node a) const { return v + f[x] > a.v + f[a.x]; } }; priority_queue<node> q; struct node2 { int x; double v; bool operator<(node2 a) const { return v > a.v; } } x; priority_queue<node2> Q; int main() { scanf("%d%d%lf", &n, &m, &e); while (m--) { scanf("%d%d%lf", &u, &v, &ww); add_edge(u, v, ww); add_edge1(v, u, ww); } for (int i = 1; i < n; i++) f[i] = inf; Q.push({n, 0}); while (!Q.empty()) { x = Q.top(); Q.pop(); if (tf[x.x]) continue; tf[x.x] = true; f[x.x] = x.v; for (int j = h1[x.x]; j; j = nxt1[j]) Q.push({p1[j], x.v + w1[j]}); } k = (int)e / f[1]; q.push({1, 0}); while (!q.empty()) { node x = q.top(); q.pop(); cnt[x.x]++; if (x.x == n) { e -= x.v; if (e < 0) { printf("%d\n", ans); return 0; } ans++; } for (int j = h[x.x]; j; j = nxt[j]) if (cnt[p[j]] <= k && x.v + w[j] <= e) q.push({p[j], x.v + w[j]}); } printf("%d\n", ans); return 0; } |
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用