启发式搜索

启发式搜索是一种对搜索到的每一个位置进行评估,然后从评估的最优位置进行搜索直到目的地,
由于搜索时对每一个位置的评估是基于直观或经验的所有叫启发式搜索

A*算法

历史:

1964年Nils Nilsson提出了A1算法,是一个启发式搜索算法,
而后又被改进成为A2算法,直到1968年,被Peter E. Hart改进成为A*算法

主要思想:

1.对于每个搜索到的点求一个估价函数f(x)。
$\large f(x)=g(x)+h(x)$
其中g(x)表示起点到当前点实际走的代价,h(x)表示当前点x到终点的估算代价。
2.并将这个搜索到的点按f(x)加入一个待搜索列表中。
3.每次从待搜索列表取出f(x)最小的点加入搜索过列表,并从这个点开始进行搜索
4.重复1。

注意:如果搜索到的一个点已经在待搜索列表(在搜索过列表不算)中
则要更新它的f值,而不是什么也不做,因为可能出现下面这种情况

红色为起点,绿色为终点,灰色为搜索过列表中的点,黄色为待搜索列表中的点,蓝色的是障碍。
如果按和终点的曼哈顿距离算h(x)则会搜索成这种情况,
这时被圈出的黄色的点g(x)=被圈出的灰色的点的g(x)+1。

这显然不是最优的g值
所以搜索时在遇到待搜索列表中的点要更新它的f值

h函数的选择

由于h函数只是一个估计值,所以对于每个题目可以有许多h函数的选择方法

选择不同的h函数会有不同的效果,但大致有两条规律:

  1. 如果h(x)>x到终点的实际代价,则可以尽快找到一个解,但不一定是最优解
  2. 如果$h(x)\le$x到终点的实际代价,则如果有解,一定是最优解
    且h(x)和x到终点的实际代价相差越大,搜到的无关节点越多

例题

luoguP1379 八数码难题

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int fac[]={, , , , , , , , };
int cantor(int a[],int k){//康托展开
int ans=,tmp;
for(int i=;i<k;i++){
tmp=;
for(int j=i+;j<k;j++){
if(a[i]>a[j])tmp++;
}
ans+=tmp*fac[k-i-];
}
return ans;
}
void uncantor(int a[],int k,int num){//逆康托展开
int b[];
for(int i=;i<k;i++)b[i]=i+;
b[k]=;
for(int i=,x;i<k;i++){
x=num/fac[k-i-],num%=fac[k--i];
a[i]=b[x]-;
for(int j=x;b[j];j++)b[j]=b[j+];
}
}
int ma,dis[][],go[][]={{,},{-,},{,},{,-}},a[],b[];
bool vis[];
int h(){//估价代价
int ans=;
for(int i=,j;i<;i++){
for(j=;j<;j++){
if(a[i]==b[j])break;
}
if(a[i])ans+=dis[i][j];
}
return ans;
}
struct Node{
int x,f,g;//x为状态的康托展开值,
bool operator < (const Node &b)const{
return f>b.f;
}
}node,w;
priority_queue<Node> q;
int astr(int now,int t){//A*算法
node.x=now;
node.f=h();
node.g=;
q.push(node);
while(!q.empty()){
w=q.top(),q.pop();
if(vis[w.x])continue;
vis[w.x]=;
if(w.x==t){
return w.f;
}
uncantor(a,,w.x);
int x,y;
for(int i=;i<;i++){
if(a[i]==){
x=i/,y=i%;break;
}
}
for(int i=;i<;i++){
int x1=x+go[i][],y1=y+go[i][];
if(x1>=&&x1<&&y1>=&&y1<){
swap(a[x1*+y1],a[x*+y]);
node.x=cantor(a,),node.g=w.g+,node.f=h()+node.g;
if(!vis[node.x])q.push(node);
swap(a[x1*+y1],a[x*+y]);
}
}
}
return ;
}
int main(){
char s[];int st,t;
sscanf("","%s",s);
for(int i=;i<;i++)b[i]=s[i]^0x30;
t=cantor(b,);
scanf("%s",s);
for(int i=;i<;i++)a[i]=s[i]^0x30;
st=cantor(a,);
vis[st]=;
for(int i=;i<;i++){
for(int j=i+;j<;j++){
dis[j][i]=dis[i][j]=j/-i/+abs(i%-j%);
}
}
memset(vis,,sizeof(vis));
printf("%d",astr(st,t));
return ;
}

IDA*

A*算法和bfs一样都要记录每个节点是否被访问过了,有些题目的状态不好表示

使用A*算法就会非常麻烦,这时就可以使用IDDFS的A*思想优化版IDA*(IDA*并不是迭代加深A*)

具体操作

具体操作和IDDFS基本一样:

  1. 确定一个限制深度,然后进行DFS
  2. 如果在限制深度内得不到解就将限制深度加深,继续DFS
  3. 如果得到解就输出

只是在dfs的时候利用A*思想估计剩余深度,如果当前深度+估计值>限制深度就退出本次搜索

例题hdu1667 The Rotation Game

/******************************************************************
IDA*
******************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int center[] = {,,,,,,,}; //中心8个点的位置
const int reversetp[] = {,,,,,,,}; //每种操作的逆操作
const int op[][] = { //从A-H操作的值的下标
{ , , ,,,, }, //A
{ , , ,,,, }, //B
{ , , , , , , }, //C
{ ,,,,,, }, //D
{ ,,,, , , }, //E
{ ,,,, , , }, //F
{ ,,,,,, }, //G
{ , , , , , , }, //H
};
int a[];
int h(){
int num[]={};
for(int i=;i<;i++){
num[a[center[i]]-]++;
}
return -max(num[],max(num[],num[]));
}
bool f;char ans[];
void modify(int x){
int w=a[op[x][]];
for(int i=;i<;i++)a[op[x][i]]=a[op[x][i+]];
a[op[x][]]=w;
}
void idastar(int d,int maxd){
if(f)return;
if(d==maxd){
if(!h())f=,ans[d]=,printf("%s\n%d\n",ans,a[]);
return;
}
if(d>maxd||d+h()>maxd)return;
for(int i=;i<;i++){
modify(i);
ans[d]=(i^0x40)+,idastar(d+,maxd);
modify(reversetp[i]);
}
}
void work(){
for(int i=;i<;i++)scanf("%d",a+i);
if(!h()){
printf("No moves needed\n%d\n",a[]);
return;
}
f=;
for(int i=;;i++){
idastar(,i);
if(f)return;
}
}
int main(){
while(~scanf("%d",a)&&a[])work();
return ;
}

启发式搜索——A*算法的更多相关文章

  1. 启发式搜索A*算法

    A* 寻路算法 (2011-02-15 10:53:11) 转载▼ 标签: 游戏 分类: 算法 概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的. 搜索区域(T ...

  2. 启发式搜索A-Star算法 【寻找 最短路径 算法】【地理几何位置 可利用的情况】

    在处理最短路径问题时,有一种启发式算法是我们应该了解的,由于其有着优秀的探索效率在各自现实项目中多有应用,它就是 A-star 算法,或  A*  算法. 个人观点: A*  算法并不保证找到的路径一 ...

  3. 启发式搜索 A*算法的OC 实现

    前两天重新学习了下A*算法,上次学习A*算法已经是5年前了,看到网上铺天盖地的A*算法都是C.C++等等其他语言的,就是没有OC 的,所以抽空写了一份.今天太晚了就不说明A*算法的细节了,大家如果想学 ...

  4. A*搜寻算法(A星算法)

    A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...

  5. 【算法入门】深度优先搜索(DFS)

    深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...

  6. 深度优先搜索(DFS)

    [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一 ...

  7. POJ 2449 Remmarguts' Date --K短路

    题意就是要求第K短的路的长度(S->T). 对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度. 但是这种方法效率太低,会扩展出很多状态,所以 ...

  8. dfs介绍

    深度优先搜索(DFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍 ...

  9. 数据结构6——DFS

    一.相关定义 深度优先遍历,也有称为深度优先搜索,简称DFS.其实,就像是一棵树的前序遍历. 初始条件:图G所有顶点均未被访问过,任选一点v. 思想:是从一个顶点V1开始,沿着一条路一直走到底,如果发 ...

随机推荐

  1. 取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏

    取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏,在MainActivity中添加以下代码: getWindow().clearFlags(WindowManager.LayoutP ...

  2. Erlang学习记录:运算符

    数学运算符 说明 详细 符号 加减乘 +-* 浮点数除 结果为浮点数 / 整数除 除数和被除数都必须是整数,结果为整数 div 整数取余 rem 逻辑运算符 说明 符号 详细 and 前后两个值都为真 ...

  3. matplotlib 画图颜色参数值及对应色卡

     matplotlib 色卡对应参数值 cnames = { 'aliceblue': '#F0F8FF', 'antiquewhite': '#FAEBD7', 'aqua': '#00FFFF', ...

  4. 0926CSP-S模拟测试赛后总结

    又一次垫底.持续低迷.20分. 赛时状态还可以.但是过于保守而不思进取.三道题目打了暴力就滚粗了. 暴力还挂掉了. T1暴力因为开小了数组挂成了0.1000的点,子序列个数我开了1e5以为足够了.结果 ...

  5. 20175323《Java程序设计》第四周学习总结

    教材学习内容总结 我用幕布记录学习过程和思路,下面是我这章的知识框架总结https://mubu.com/doc/ffMhY6FVc0 教材学习中的问题和解决过程 问题1:教材121页的例六Examp ...

  6. 记录一次hexo托管到coding失败,页面总是404,可是相同的代码托管到github是没问题的。

    文章目录 问题描述: 问题原因: 问题解决 2019.1.23 问题,coding又挂了. 弃疗 个人博客:https://mmmmmm.me 源码:https://github.com/dataiy ...

  7. Pycharm中如何加载多个项目同时存在

    原文地址: http://www.cnblogs.com/mrgavin/p/6382406.html 今天在使用Pycharm工具练习Python时遇到一个疑问:在已存有项目A工程的前提下如何新建另 ...

  8. AtCoder ABC 130E Common Subsequence

    题目链接:https://atcoder.jp/contests/abc130/tasks/abc130_e 题目大意 给定一个长度为 N 的序列 S 和一个长度为 M 的序列 T,问 S 和 T 中 ...

  9. uoj#370【UR #17】滑稽树上滑稽果

    题目 低智选手果然刷不动uoj 首先考虑一下构造一棵树显然是骗你玩的,按位与这个东西越做越小,挂到链的最下面显然不会劣于挂到之前的某一个点下面,所以我们只需要求一个排列使得答案最小就好了 设\(A=\ ...

  10. P1417 烹调方案 /// DP(假设 简化公式 排序)

    题目大意: https://www.luogu.org/problemnew/show/P1417 题解 看第一份方法的公式 排序后01背包 #include <bits/stdc++.h> ...