IDA*算法 启发式搜索

八数码难题

1、IDA*算法是带有评估函数的迭代加深DFS算法。

所谓迭代加深就是每次限制搜索深度, 这样可以在整个搜索树深度很大而答案深度又很小的情况下大大提高效率

使k从1开始不断加深枚举, 作为最大步数进行迭代加深搜索判断,而对于不用移动的情况可以一开始直接特判。

2、A*估价函数

当前步数+估价函数值>枚举的最大步数 则直接返回

当然这只是基本思路,搜索还可以有很大优化

3、我们在搜索中再加入最优性剪枝, 显然当前枚举下一个状态时如果回到上一个状态肯定不是最优, 所以我们在枚举下一状态时加入对这种情况的判断,将状态数组对称排列会很方便进行这一操作:  

int nxtx[]={0,1,-1,0};
int nxty[]={1,0,0,-1};
#include<iostream>
#include<string>
#include<map>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

char ss[15];
int ans[4][4]=
{{0,0,0,0},
 {0,1,2,3},
 {0,8,0,4},
 {0,7,6,5}};
int a[5][5],k,judge;
int nxtx[]={0,1,-1,0};
int nxty[]={1,0,0,-1};

int check()
{
    for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
    if(ans[i][j]!=a[i][j])return 0;
    return 1;
}

int test(int step)
{
    int cnt=0;
    for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
    if(ans[i][j]!=a[i][j]){ if(++cnt+step>k) return 0;}
    return 1;
}

void A_star(int step,int x,int y,int pre)//pre上次的移动操作
{
    if(step==k){ if(check())judge=1; return;}达到当前限制的最大深度
    if(judge) return;
    for(int i=0;i<4;++i)
    {
        int nx=x+nxtx[i],ny=y+nxty[i];
        if(nx<1||nx>3||ny<1||ny>3||pre+i==3) continue;//加入了上述最优性剪枝,防止到上次的位置
        swap(a[x][y],a[nx][ny]);
        if(test(step)&&!judge) A_star(step+1,nx,ny,i);//A*估价合法再向下搜索
        swap(a[x][y],a[nx][ny]);
    }
}

int main()
{
    int x,y;
    scanf("%s",&ss);
    for(int i=0;i<9;++i)
    {
        a[i/3+1][i%3+1]=ss[i]-'0';
        if(ss[i]-'0'==0)x=i/3+1,y=i%3+1;
    }
    if(check()){printf("0");return 0;}//特判不用移动
    while(++k)//枚举最大深度
    {
        A_star(0,x,y,-1);
        if(judge){printf("%d",k);break;}
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
A*算法IDA*算法都是启发搜索算法,它们都是用于解决最短路径问题的常用算法。其中,A*算法搜索时利用了启发函数来估计从当前节点到目标节点的距离,从而选择最优的节点进行搜索。而IDA*算法则是在A*算法基础上做出的改进,其主要区别是不使用任何额外的内存空间,而是将估价函数的值作为深度限制,直到找到目标节点或者超过深度限制为止。 具体来说,A*算法维护一个open列表和一个closed列表。open列表中保存了待搜索的节点,closed列表中保存已经被搜索过的节点。每次从open列表中选择一个f值最小的节点进行扩展,并将其加入closed列表中。扩展时,对于当前节点的每个子节点计算估价函数值f(n)=g(n)+h(n),其中g(n)是从起点到当前节点的实际代价,h(n)是从当前节点到目标节点的估计代价。这样,每次选择f值最小的节点进行扩展时,就能够尽可能地朝着目标节点前进。 IDA*算法则是将A*算法中的open列表替换成一个栈,在搜索时将当前搜索深度作为阈值,不断更新阈值来限制搜索深度。具体来说,每次从起点开始,将阈值设置为起点到目标节点的估价函数值,然后进行深度优先搜索。如果搜索到某个节点的f(n)>threshold,则将其返回,并将阈值更新为f(n)。这样,IDA*算法通过不断增加深度限制来逐步逼近最短路径,直到找到目标节点或者搜索到达最大深度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

El.十一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值