图的搜索进阶A*,IDA*

本文详细介绍了A*和IDA*两种图搜索算法。A*算法通过结合优先队列BFS与估价函数,确保找到最优解的同时提高搜索效率。IDA*则是将估价函数应用于迭代加深的DFS,通过限制深度与估价函数估计步数来优化搜索。文章通过实例分析了这两种算法的实现步骤和复杂度,并给出了在不同问题上的应用策略。
摘要由CSDN通过智能技术生成

一、A * :

  估价函数的设计准则:估值f(state)≤未来实际代价g(state)。
  A * 算法的实现,A * =优先队列BFS+估价函数。
  1。优先队列BFS算法维护了一个优先队列,不断从堆中取出当前代价最小的状态
进行扩展。每个状态第一次从堆中取出时,就得到了从初态到该状态的最小代价。
  如果给定一个目标状态,需要求出从初态到目标状态的最小代价,那么优先队列
BFS这个优先策略是不完善的。

  2。为了提高搜索效率,我们很自然的想到,可以对未来可能产生的代价进行预估。
详细的讲:我们设计一个估价函数,以任意状态为输入,计算出从该状态到目标状态所
需代价的估计值。在搜索中,仍然维护一个堆,不断从堆中取出 当前代价+未来估价 最小的状态进行扩展

  3。为了保证第一次从堆中取出目标状态时得到的就是最优解,我们设计的估价函数需要满足一个基本准则:估价函数的估值不能大于未来实际代价,估价比实际代价更优。

  4。这种带有估价函数的优先队列BFS就称为A * 算法。只要保证对于任意状态state,都有f(state)≤g(state),A * 算法就一定能在目标状态第一次从堆中被取出时得到最优解,并且在搜索过程中每个状态只需要被扩展一次(之后再被取出就可以直接忽略)。估价f(state)越准确,越接近g(state),A * 算法的效率就越高。如果估价始终为5.0,就等价于普通优先队列BFS。

  5。A * 算法提高搜索效率的关键,就在于能否设计出一个优秀的估价函数。估价函数在满足上述设计准则的前提下,含应该尽可能反映未来实际代价的变化趋势和相对大小关系,这样搜索才会较快的逼近最优解。

例题:POJ2449: 第K短路。
  对于任意正整数i和任意节点x,当第i次从堆中取出包含节点x的二元组时,对应的dist值就是从S到x的第i短路。

  使用优先队列BFS在最坏的情况下的复杂度为O(K (N+M)log(N+M))。这道题目给定了起点和终点,求长度最短(代价最小)的路径,可以考虑使用A*算法提高搜索效率。
  得到以下解题步骤:
  (1)预处理出各个节点x到终点T的最短路长度f(x)——这等价于在反向图上以T为起点求解单源最短路径问题,可以在O((N+M)log(N+M) )的时间内完成。

  (2)建立一个二叉堆,存储一些二元组(x,dist+f(x)),其中x为节点编号,dist表示S到x当前走过的距离。起初堆中只有(S,0+f(S))。

  (3)从二叉堆中取出dist+f(x)最小的二元组(x,dist+f(x)),然后沿着从x出发的每条边(x,y)进行扩展。如果节点y被取出的次数尚未到达K,就把新的二元组(y,dist+lenth(x,y)+f(y))插入堆中。

  (4)重复2-3步,直至第k次取出包含终点T的二元组,此时二元组中的dist值就是从S到T的第K短路。

  A * 算法的复杂度上届与优先队列BFS相同。不过,因为估价函数的作用,图中很多节点的访问次数都远小于k。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<queue>
#include<cmath>
#include<string>
#define ll long long
using namespace std;
const int maxn=10010;
const int mmax=100010;
int n,m,s,t,k;
int x,y,z;
int dis[maxn],head[maxn],ver[mmax],nt[mmax],edge[mmax];
int _head[maxn],_ver[mmax],_nt[mmax],_edge[mmax];
int tot,_tot;
bool ha[maxn];
int num[maxn];

struct node
{
   
    int x;
    int dx;
    int fx;
    node () {
   }
    node(int a,int b,int c)
    {
   
        x=a;
        dx=b;
        fx=c;
    }
    friend bool operator <(const node &a,const node &b)
    {
   
        return a.dx+a.fx>b.dx+b.fx;
    }
};

void add(int x,int y,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值