A*算法

本文详细介绍了如何使用A*算法解决经典的八数码问题,包括算法原理、估价函数和数据结构。通过实例展示了算法的运行过程,包括扩展节点的计算和目标状态的寻找,同时提供了C语言实现的程序代码。
摘要由CSDN通过智能技术生成

A*算法八数码问题

  • 八数码问题描述

    八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中,这里空格用数字0代替。给定九宫格的初始状态重点内容,要求在有限步的操作内,使其转化为目标状态,且所得到的解是代价最小解(即移动的步数最少)并打印出求解路径及求解的扩展节点。

  • A*算法

    (1)A*算法;是对A算法的估价函数f(n)=g(n)+h(n)加上某些限制后得到的一种启发式搜索算法。A*算法对A算法中的g(n)和h(n)分别提出如下限制:第一,g(n)是对最小代价g*(n)的估计,且g(n)>0;第二,h(n)是最小代价h*(n)的下界,即对任意节点n 均有h(n)≤h*(n)。即满足上述两条限制的A算法称为A*算法。
    (2)估价函数;用来估算节点希望程度的量度,叫估价函数f(x),f(x)=g(x)+h(x)。g(x)为从初始节点到当前节点已经付出的代价,h(x)为从当前节点到目标节点的最优路径的估计代价。本算法中令g(x)为当前节点的深度depth;
    h(x)为当前节点每个数字位与目标节点数字位间距离和distance,进一步考虑当前结点与目标结点的距离信息,可以令启发函数h ( n )为当前8个数字位与目标结点对应数字位距离和(不考虑中间路径),满足h ( n ) <= h * ( n ), 且对于目标节点有 h ( t ) = 0,对于结点m和n (n 是m的子结点) 有h ( m ) – h ( n ) <= 1满足单调限制条件;也可以考虑令启发函数h ( n )为放错棋子移到目标位置的距离的总和;当然也可以如A算法令启发函数h ( n )为放错棋子的数目;
    在这里使用的启发函数h ( n )为w ( n ) +3*d ( n ),w ( n )为放错棋子的数目,
    d ( n )为放错棋子移到目标位置的距离的总和;
    (3)open和closed表的数据结构表示;对open表的操作,每次需要得到所有待扩展结点中 f 值最小的那个结点。closed表存储已扩展的结点间的扩展关系,主要用于输出路径。closed 表中任意一个结点都存储有它的前驱结点的信息,考虑closed表中任意一个结点,如果它是初始结点,它没有前驱结点,如果不是根结点,扩展该结点时它的前驱结点已经记录。从而在closed表中形成扩展关系的树状结构。因为只需要前驱点的下标位置,可以用数组实现。每个结点记录8数码格局和它的前驱结点的下标。

  • 算法分析

    1. 把S放入open表,记f = h,令closed为空表;
    2. loop:直至找到目标节点为止。若open表为空,则失败;
    3. 选取open表中(未设置过的)具有最小f的节点为最佳节点bes,并把它放入closed表;
    4. 若bes为一目标节点,则成功求得一解;
    5. 若bes不是目标节点,则扩展之,产生后继节点suc;
    6. 对每个后继节点suc,进行下列过程:
      a. 建立从后继节点suc返回最佳节点bes的指针;
      b. 计算g(suc) = g(bes) + g(bes,suc);
      c. 若后继节点suc在open表或clsoed表中,则称此节点为old,并把它添加至最佳节点bes的后继节点表中,比较新旧路径代价:
      1) 若g(suc)小于g(old),则重新确定old的父辈节点为bes节点,记下较小代价
      g(old),并修正f(old)值。转7;
      2) 若至old节点的代价较低或一样,则停止可扩展节点;转7;
    7. 计算f的值;
    8. Go loop
  • 源程序
    程序是用C实该程序实现了A*算法寻找最优的路径,并且把所有的扩展节点给打印出来,打印扩展节点时,运行程序得到的结果中从上至下,第一大列对应的便是解决方案的路径,同时也是父节点与子节点之间的关系,
    Step n 这一代的所有节点对应的父节点都是Step n-1 代节点中最左边的那个节点
    棋子目标状态:
    1 2 3
    8 0 4
    7 6 5

  • 程序实现如下 :


#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
struct node
{
    int start[3][3];
    int f;    //估价函数
    int g;    //节点深度
    int h;    //启发函数
    int x;    //空格的位置
    int y;
    struct node * father;
    struct node * next;
};
static int target[3][3] = { 1,2,3,8,0,4,7,6,5 };//目标状态
static int sum_num = 0;
static int same[100];

int gets_h(node*s);
int same_node(node*a, node*b);//节点是否相等
node*In_list(node*L, node*n);//节点n是否在L表中

void zero_place(node*s)
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            if (s->start[i][j] == 0)
            {
                s->x = i;
                s->y = j;
                return;
            }
        }
    }
}
void _input(node* s)
{
    int i, j;
    printf("测试情况:输入\n\n");
    printf("****2 8 3****\n");
    printf("****1 6 4****\n");
    printf("****7 0 5****\n\n");
    printf("请输入初始位置:(3*3)\n");
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            scanf("%d", &s->start[i][j]);
        }
        printf("\n");
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值