启发式搜索

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

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. this 、typeof、false、parseInt()、this、arguments、Array和object判断

    typeof typeof (undefined) 不会报错 undefined object Number boolean function String 返回值为字符串类型 false .fals ...

  2. The Battle of Chibi

    The Battle of Chibi 给出一段长度为n的序列\(\{a_i\}\),求其中长度为m的严格上升子序列个数\(mod\ 10^9+7\),\(n\leq 10^3\). 解 不难想到设\ ...

  3. Python 学习杂项

    #print("Hello World!") #name = "nihfjkds" age = 454 num1 = 1 num2 = 2 #print(nam ...

  4. CSS——滑动门技术及应用

    先来体会下现实中的滑动门,或者你可以叫做推拉门: 滑动门出现的背景 制作网页时,为了美观,常常需要为网页元素设置特殊形状的背景,比如微信导航栏,有凸起和凹下去的感觉,最大的问题是里面的字数不一样多,咋 ...

  5. Byte[]和Stream相互转换

    C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...

  6. Linux下编译VLC for Android源代码总结

    转:http://blog.chinaunix.net/uid-26611383-id-3678766.html 由于项目需要,需要一个在android平台能够支持RTSP协议的播放器,由于之前没有a ...

  7. 命令学习_ping

    PING: ping是一个所有操作系统都支持的简单工具.我么可以利用ping来解析DNS 的A record和PTRrecord. A记录是将域名映射到IP地址,这个是ping的缺省功能, ping同 ...

  8. k8s常用的资源

    1. 创建pod资源 pod是最小的资源单位 任何一个k8s资源都可以有yml清单文件来定义 k8s yaml的主要组成 apiVersion: v1 api版本 kind: pod 资源类型 met ...

  9. iOS逆向系列-Cycript

    概述 Cycript 是Objective-C++.ES(JavaScript).Java等语法的混合物. 可以用来探索.修改.调试正在运行的Mac\iOS App. 通过Cydia安装Cycript ...

  10. Java虚拟机性能管理神器 - VisualVM(7) 排查JAVA应用程序线程泄漏【转】

    Java虚拟机性能管理神器 - VisualVM(7) 排查JAVA应用程序线程泄漏[转] 标签: javajvm线程泄漏 2015-03-11 19:47 1098人阅读 评论(0) 收藏 举报   ...