A*

构成

dijkstra 优先队列优化 \(+\) BFS \(+\) 玄学长度预估 \(=\) Astar。

解释

dijkstra 优先队列优化:每一次放进优先队列(小根堆)里的是 起点到这个状态的步数 \(+\) 当前点到终点的预估步数,在终点第一次出队时结束,此时得到的值必然为最小值(求第 \(k\) 短的路就出队 \(k\) 次)。

tip1: 每个点第一次入队所得出的步数不一定是初始状态到当前状态的最优解,所以一个状态可能被以前的状态更新多次,每次有走到新的状态时要判断当前方法是否比之前的方法更优,更优才把入队。

BFS:应该不用说吧 QWQ。

玄学长度预估:可以是曼哈顿距离(如八数码这题),甚至可以把终点变成起点,反着跑一遍 dijkstra(比如下下题),反正就是对这个状态还有几步可以达到最后状态的预估。

tip2: 预估值只能小于等于此状态到最终状态的真正步数。

例题

洛谷P1379八数码难题

#include <bits/stdc++.h>
#define PIS pair <int, string>
#define PII pair <int, int>
#define LL long long
#define DB double
#define umap unordered_map
#define x first
#define y second namespace FastIO
{
inline void read(int MOD, int &ret){
ret = 0;
char ch = getchar();int ngtv = 1;
if(MOD == 0) {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (ret << 3) + (ret << 1) + (ch ^ 48);ch = getchar();}}
else {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (((ret << 3) + (ret << 1)) % MOD + (ch ^ 48) % MOD) % MOD;ch = getchar();} }
ret *= ngtv;}
inline void cread(char &ch){ch = getchar();while(ch == ' ' || ch == '\n' || ch == '\r' || ch == 0) ch = getchar();}
}
using namespace FastIO;
using namespace std; const int N = 1e6 + 10;
string start, seq;
umap <string, int> dist;
priority_queue <PIS, vector <PIS>, greater <PIS> > heap;
int d[2][4] = {{1, 0, 0, -1}, {0, -1, 1, 0}};
string op = "dlru", target = "123804765";
PII xi[9] = {{2, 2}, {0, 0}, {0, 1}, {0, 2}, {1, 2}, {2, 2}, {2, 1}, {2, 0}, {1, 0}}; int f(string s)
{
int res = 0, now;
for(int i = 0; i < 9; i ++ )
now = s[i] - '0', res += abs(xi[now].x - i / 3) + abs(xi[now].y - i % 3);
return res;
} void bfs(string start)
{
dist[start] = 0;
heap.push({f(start), start}); while(heap.size())
{
auto t = heap.top();
heap.pop();
if(t.y == target)
{
printf("%d\n", dist[t.y]);
return ;
} int x, y, xx, yy;
for(int i = 0; i < 9; i ++ )
if(t.y[i] == '0')
{
x = i / 3, y = i % 3;
break;
} string source = t.y;
for(int i = 0; i < 4; i ++ )
{
xx = x + d[0][i], yy = y + d[1][i];
if(xx < 0 || xx >= 3 || yy < 0 || yy >= 3)
continue;
t.y = source;
swap(t.y[x * 3 + y], t.y[xx * 3 + yy]);
if(dist.count(t.y) == 0 || dist[t.y] > dist[source] + 1)
{
dist[t.y] = dist[source] + 1;
heap.push({dist[t.y] + f(t.y), t.y});
}
}
}
} signed main()
{
char c;
for(int i = 0; i < 9; i ++ )
{
cread(c);
if(c != '0')
seq += c;
start += c;
} int judge = 0;
for(int i = 0; i < 9; i ++ )
for(int j = i + 1; j < 9; j ++ )
if(seq[i] > seq[j])
judge ++ ; bfs(start); return 0;
}

Acwing第k短路

#include <bits/stdc++.h>
#define PII pair <int, int>
#define PIII pair <PII, int>
#define x first
#define y second
#define LL long long
#define DB double
#define endl '\n' namespace FastIO
{
inline void read(int MOD, int &ret){
ret = 0;
char ch = getchar();int ngtv = 1;
if(MOD == 0) {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (ret << 3) + (ret << 1) + (ch ^ 48);ch = getchar();}}
else {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (((ret << 3) + (ret << 1)) % MOD + (ch ^ 48) % MOD) % MOD;ch = getchar();} }
ret *= ngtv;}
inline void cread(char &ch){ch = getchar();while(ch == ' ' || ch == '\n' || ch == '\r' || ch == 0) ch = getchar();}
}
using namespace FastIO;
using namespace std; const int N = 1010;
bool vis[N];
int n, m, s, t, k;
int u, v, w, dist[N], cnt[N];
vector <PII> v1[N], v2[N]; void dijkstra()
{
priority_queue <PII, vector <PII>, greater <PII> > q; memset(dist, 0x3f, sizeof dist);
dist[t] = 0;
q.push({0, t});
vis[t] = 1;
while(q.size())
{
auto tt = q.top();
q.pop();
if(vis[tt.y]) continue;
vis[tt.y] = 1; for(PII to : v2[tt.y])
{
if(tt.x + to.y < dist[to.x])
{
dist[to.x] = tt.x + to.y;
q.push({dist[to.x], to.x});
}
}
}
} int Astar()
{
priority_queue <PIII, vector <PIII>, greater <PIII> > q;
q.push({{dist[s], 0}, s}); while(q.size())
{
auto tt = q.top();
q.pop();
int d = tt.x.y, node = tt.y;
cnt[node] ++ ;
if(cnt[t] == k)
return d; for(auto to : v1[node])
if(cnt[to.x] < k)
q.push({{d + to.y + dist[to.x], d + to.y}, to.x});
} return -1;
} signed main()
{
read(0, n), read(0, m);
while(m -- )
{
read(0, u), read(0, v), read(0, w);
v1[u].push_back({v, w});
v2[v].push_back({u, w});
}
read(0, s), read(0, t), read(0, k);
if(s == t) k ++ ; dijkstra(); printf("%d\n", Astar()); return 0;
}

IDA*

思想

在 DFS 时,如果当前深度 \(+\) 预估到达结束深度(\(\le\) 真实深度) \(\ge maxdepth\) 就跳出 DFS

与 A* 的区别

与 A*算法有异曲同工之妙,区别是 A*是 BFS 的剪枝,IDA* 是 DFS 的剪枝。

例题

Acwing 180 排书

洛谷

P10488 Booksort

#include <bits/stdc++.h>
#define PII pair <int, int>
#define LL long long
#define DB double
#define endl '\n' namespace FastIO
{
inline void read(int MOD, int &ret){
ret = 0;
char ch = getchar();int ngtv = 1;
if(MOD == 0) {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (ret << 3) + (ret << 1) + (ch ^ 48);ch = getchar();}}
else {while(ch < '0' || ch > '9'){if(ch == '-') ngtv = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ret = (((ret << 3) + (ret << 1)) % MOD + (ch ^ 48) % MOD) % MOD;ch = getchar();} }
ret *= ngtv;}
inline void cread(char &ch){ch = getchar();while(ch == ' ' || ch == '\n' || ch == '\r' || ch == 0) ch = getchar();}
}
using namespace FastIO;
using namespace std; const int N = 25;
int T, n, q[N], w[6][N]; int f()
{
// 由于每次交换只会影响三本书的后面位置,那最少就会交换当前不满足条件的书的本数 / 3(上取整)
int tot = 0;
for(int i = 0; i < n - 1; i ++ )
if(q[i] + 1 != q[i + 1]) tot ++ ;
// 等价于除与3上取整
return (tot + 2) / 3;
} bool check()
{
// 判断当前情况是否满足题意(为升序)
for(int i = 0; i < n - 1; i ++ )
if(q[i] + 1 != q[i + 1]) return false;
return true;
} bool dfs(int depth, int max_depth)
{
// IDA*剪枝
if(depth + f() > max_depth) return false;
if(check()) return true; // 枚举去除书本的数量(区间长度)
for(int len = 1; len <= n; len ++ )
// 枚举取书的左端
for(int l = 0; l + len - 1 < n; l ++ )
{
int r = l + len - 1; // 计算右端
for(int i = r + 1; i < n; i ++ )
{
// 暂时将q储存在w[depth]中,方便回溯
memcpy(w[depth], q, sizeof q);
// 开始挪书
int y = l;
for(int x = r + 1; x <= i; x ++, y ++ ) q[y] = w[depth][x];
for(int x = l; x <= r; x ++ , y ++ ) q[y] = w[depth][x];
// 如果可以成功就无需继续枚举,直接返回
if(dfs(depth + 1, max_depth)) return true;
// 回溯
memcpy(q, w[depth], sizeof q);
}
} // 无解
return false;
} signed main()
{
read(0, T); while(T -- )
{
read(0, n);
for(int i = 0; i < n; i ++ )
read(0, q[i]); int depth = 0;
// 从小到大枚举最大深度
while(depth < 5 && !dfs(0, depth)) depth ++ ; if(depth >= 5) puts("5 or more");
else printf("%d\n", depth);
} return 0;
}

搜索优化之 A* 与 IDA*的更多相关文章

  1. 一次 ElasticSearch 搜索优化

    一次 ElasticSearch 搜索优化 1. 环境 ES6.3.2,索引名称 user_v1,5个主分片,每个分片一个副本.分片基本都在11GB左右,GET _cat/shards/user 一共 ...

  2. 【随笔】Android应用市场搜索优化(ASO)

    参考了几篇网上的关于Android应用市场搜索优化(ASO)的分析,总结几点如下: 优化关键字:举例目前美团酒店在各Android市场上的关键字有“美团酒店.钟点房.团购.7天”等等,而酒店类竞对在“ ...

  3. 针对TianvCms的搜索优化文章源码(无版权, 随便用)

    介绍: 搜索优化虽然不是什么高深的技术, 真正实施起来却很繁琐, 后台集成搜索优化的文章可以便于便于管理, 也让新手更明白优化的步奏以及优化的日常. 特点: 根据自己的经验和查阅各种资料整理而成, 相 ...

  4. seo搜索优化教程09 - seo搜索优化外链优化

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉科技强势推出seo搜索优化教程.此为seo教程第九课 网络营销推广中有句行话,叫做"内容为王,外链为王",可见外链对于 ...

  5. seo搜索优化教程10-黑帽SEO

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉科技强势推出seo搜索优化教程.此为seo教程第十课 学习黑帽SEO并不是教大家如何作弊,而是想让大家避免使用黑帽SEO手法,从而导致被搜 ...

  6. seo搜索优化教程11-seo搜索优化关键词策略

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉科技强势推出seo搜索优化教程.此为seo教程第11课 关键词在seo搜索优化中有着重要的地位,本节主要讲解seo搜索优化中关键词优化的相 ...

  7. seo搜索优化教程12-网站SEO诊断

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉信息科技强势推出seo搜索优化教程.此为seo教程第12课 行业分析 在搜索引擎中检索自己的站点,在检索结果及相关网站中分析自己在行业内的 ...

  8. seo搜索优化教程13-SEO搜索引擎站点收录

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉科技强势推出seo搜索优化教程.此为seo教程第13课 想要用户能够在搜索引擎中通过关键词搜索到您的页面信息,首先要做的是让搜索引擎收录您 ...

  9. seo搜索优化教程14-seo搜索优化实战

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉信息科技强势推出seo搜索优化教程.此为seo教程第14课 根据前面学习的seo搜索优化内容,星辉科技进行总结性的分析,形成一份标准的se ...

  10. seo搜索优化技巧01-seo外链怎么发?

    在seo搜索优化中,seo外链的作用并没有早期的作用大了.可是高质量的外链对关键词的排名还是很重要的.星辉信息科技对seo外链怎么发以及seo外链建设中的注意点进行阐述. SEO外链如何做 SEO高质 ...

随机推荐

  1. Manim实现旋转变色特效

    在数学动画的世界里,旋转与变色特效无疑是最能吸引观众眼球的元素之一. 今天,就让我们一起探索如何使用Manim框架来实现自定义的旋转变色特效吧! 1. 实现原理 Manim的动画魔法源于Animati ...

  2. Spring注解之@Value注解读取配置文件属性和设置默认值

    概述   在Spring 组件中,通常使用@Value注解读取 properties 文件的配置值.但如果在配置文件或启动参数中未指定对应的参数值,则项目在启动的时候会抛出异常,导致服务启动失败,异常 ...

  3. Django Web应用开发实战第二章

    一.基本配置信息 """ Django settings for myblog project. Generated by 'django-admin startproj ...

  4. java如何启动时定义并初始化一个全局变量(内存中)

    前言 java如何启动时定义并初始化一个全局变量(内存中),项目启动时,通过读取配置文件来构建一个实体类对象,然后在之后可以直接使用,而不是每次使用都要进行构建 前置准备 实体类结构 package ...

  5. Go Channel介绍

    一.简单说明 Channel是Go中的一个核心类型,可以看做是一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯. 1.1 操作符 这里Channel的操作符是箭头<-,箭头的指向就是数 ...

  6. 详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路

    袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼.安全为底线.提效为⽬标.中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代.技术创新.服务细化和性能升级. 在数栈过 ...

  7. 我的 Vibe Coding 的第一个项目

    大家好,我是 Immerse,一名独立开发者.内容创作者. 关注公众号:#沉浸式趣谈,获取最新文章(更多内容只在公众号更新) 个人网站:https://yaolifeng.com 也同步更新. 转载请 ...

  8. 一个基于 .NET 8 开源免费、高性能、低占用的博客系统

    前言 今天大姚给大家分享一个基于 .NET 8 开源免费(MIT license).高性能.高安全性.低占用的博客系统:Masuit.MyBlogs. 项目介绍 Masuit.MyBlogs 是一个基 ...

  9. C++ 临时变量的释放规则

    简介 临时变量是在什么时候进行释放的呢? 委员会将注意力集中到"语句结束位置",很自然的,这种选择被通俗地称做 EOS (End Of Statement) .问题是如何精确定义 ...

  10. CGI 简单的python显示的页面

    简介 python 进行服务器的页面的显示 cgi common gateway interface 公用网关接口 简单操作 python3 -m http.server --cgi 8001 新建一 ...