pku 1077 Eight 经典8数码问题 单向BFS + A* BFS + 双向BFS

本文介绍了使用单向BFS、A*搜索及双向BFS等算法解决八数码问题的具体实现,并对比了不同算法的效率。通过哈希方法进行状态判重,利用优先队列优化搜索过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题的判重的状态的保存用到了全排列的变进制hash方法.

详细的解释见:

http://www.cppblog.com/longzxr/archive/2009/08/04/92151.html

 

下面是我三个版本的算法实现

分别为:

    单向BFS

    A* BFS

    双向BFS

对于本题, 效率递增.

 

 

一. 下面是单向BFS算法的实现

目前我的效率只有907MS, 险超时.

Memory: 4132K, Time: 907MS

 

 

二. 加上A*算法估价后的A*搜索代码

Memory: 3868K, Time: 391MS

 

 

 

三. 这是使用双向BFS的代码, 事实证明, 这题还是使用双向BFS更快.

Rank: 207 Memeory: 3232K, Time: 0MS

 

附:

IDA*算法:

#include <stdio.h>
#include <string.h>
#define ABS(x) ((x)<0?-(x):(x))
typedef struct
{
    int stat[10];
    int x;
}node_t;
node_t st;
int stack[1000002];
int dist[10][10];
/*
 *  d --  0
 *  r --- 1
 *  u --- 2
 *  l --- 3
 */
char act[] = "drul";
int dir[4] = {3, 1, -3, -1};
int mv[10][5] = {{0},
                {2, 0, 1},      /* 1 */
                {3, 0, 1, 3},   /* 2 */
                {2, 0, 3},      /* 3 */
                {3, 0, 1, 2},   /* 4 */
                {4, 0, 1, 2, 3},/* 5 */
                {3, 0, 2, 3},   /* 6 */
                {2, 1, 2},      /* 7 */
                {3, 1, 2, 3},   /* 8 */
                {2, 2, 3}       /* 9 */
                };
int found, top, min;
int get_dist(int i, int j)
{
    int x1 = (i - 1) / 3 + 1;
    int y1 = (i - 1) % 3 + 1;
    int x2 = (j - 1) / 3 + 1;
    int y2 = (j - 1) % 3 + 1;
    return ABS(x1 - x2) + ABS(y1 - y2);
}
void init_dist()
{
    int i, j;
    for(i = 1;i <= 9; i++)
        for(j = 1;j <= 9; j++) dist[i][j] = get_dist(i, j);
}
int heur(node_t node)
{
    int sum = 0, i;
    for(i = 1;i <= 9; i++) sum += dist[i][node.stat[i]];
    return sum;
}
int is_solvable(node_t st)
{
    int res = 0, i, j;
    for(i = 1;i <= 9; i++)
        for(j = 1;j < i; j++) if(st.stat[i] < st.stat[j]) res++;
    res += dist[9][st.x];
    return (res & 1) == 0;
}
int init()
{
    char str[2];
    int i;
    for(i = 1;i <= 9; i++)
    {
        if(scanf("%s", str) == EOF) return 0;
        if(str[0] == 'x')
        {
            st.stat[i] = 9;
            st.x = i;
        }
        else st.stat[i] = str[0] - '0';
    }
    return 1;
}
void output()
{
    int i;
    for(i = 1;i <= top; i++) printf("%c", act[stack[i]]);
    printf("\n");
}
void dfs(int p, int dp, int maxdp)
{
    int f = heur(st);
    int i, k, t;
    if(min > f) min = f;
    if(f + dp > maxdp || found) return;
    if(f == 0)
    {
        output();
        found = 1;
        return;
    }
    for(i = 1;i <= mv[p][0]; i++)
    {
        k = mv[p][i];
        t = dir[k] + p;
        st.stat[p] = st.stat[t];
        st.stat[t] = 9;
        stack[++top] = k;
        dfs(t, dp + 1, maxdp);
        top--;
        st.stat[t] = st.stat[p];
        st.stat[p] = 9;
    }
}
void ida_star(node_t st)
{
    int maxdp = heur(st);
    found = 0;
    while(found == 0)
    {
        min = 0x7fffffff;
        top = 0;
        dfs(st.x, 0, maxdp);
        maxdp += min;
    }
}
int main()
{
    init_dist();
    while(init())
    {
        if(is_solvable(st) == 0)
        {
            printf("unsolvable\n");
            continue;
        }
        ida_star(st);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值