【oj】八数码

本文介绍了一种使用双向BFS算法解决八数码问题的方法。通过从初始状态和目标状态同时进行搜索,有效地减少了搜索时间和空间复杂度。文章详细展示了如何实现状态转移、检查重复状态以及更新搜索队列等关键步骤。

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

/*全凭自己理解写的野鸡双向bfs,总算过了oj,就先这样吧*/

#include<stdio.h>
#include<string.h>
#include<memory.h>
#define N 370000
int num[N],parent[N],son[N],step=0,markn=0,markp=0,marks=0,temp[9];
int num1[N],parent1[N],son1[N],markn1=0,markp1=0,marks1=0;
int hash(int*a){//将一个九宫格转化为一个int返回
    int i,result=0;
    for(i=0;i<9;i++)result=result*10+a[i];
    return result;
}
int move(int a,int b,int c){//对c进行移动,交换a,b,位置
    int d,i;
    int ka=10,kb=10;
    int numa,numb;
    for(i=0;i<8-a;i++)ka*=10;
    for(i=0;i<8-b;i++)kb*=10;
    numa=(int)(c%ka)/(ka/10);
    numb=(int)(c%kb)/(kb/10);
    ka/=10,kb/=10;
    int re=c-numa*ka-numb*kb+numa*kb+numb*ka;
    return re;
}
int check(int a){//判断是否重复
        int i;
        for(i=0;num[i]!=0;i++){
            if(a==num[i])return 1;//有重复
        }
    return -1;//无重复
}
int check1(int a){//判断是否重复
        int i;
        for(i=0;num1[i]!=0;i++){
            if(a==num1[i])return 1;//有重复
        }
    return -1;//无重复
}
void bfs(){
    int i,j,k;
    memset(son,0,sizeof(son));
    memset(son1,0,sizeof(son1));
    for(i=0;i<markn1;i++)
            if(check(num1[i])==1)return;
    step++;
    marks1=0;
    for(i=0;i<markp1;i++){
        k=0;
        int p=1;
        while((int)(parent1[i]/p)%10!=0){k++;p*=10;}
        k=8-k;
        if(k%3>0){
            int x=move(k,k-1,parent1[i]);
            if(check(x)==1)return;
            if(check1(x)==-1){
                son1[marks1]=x;
                num1[markn1]=x;
                marks1++,markn1++;
            }
        }
        if(k%3<2){
           int x=move(k,k+1,parent1[i]);
           if(check(x)==1)return;
          if(check1(x)==-1){
                son1[marks1]=x;
                num1[markn1]=x;
                marks1++,markn1++;
            }
        }
        if(k>2){
            int x=move(k,k-3,parent1[i]);
            if(check(x)==1)return;
           if(check1(x)==-1){
                son1[marks1]=x;
                num1[markn1]=x;
                marks1++,markn1++;
            }
        }
        if(k<6){
            int x=move(k,k+3,parent1[i]);
            if(check(x)==1)return;
            if(check1(x)==-1){
                son1[marks1]=x;
                num1[markn1]=x;
                marks1++,markn1++;
            }
        }
    }
        memcpy(parent1,son1,sizeof(son1));
        markp1=marks1;

    step++;
    marks=0;
    for(i=0;i<markp;i++){
        k=0;
        int p=1;
        while((parent[i]/p)%10!=0){k++;p*=10;}
        k=8-k;
        if(k%3>0){
            int x=move(k,k-1,parent[i]);
            if(check(x)==-1){
                son[marks]=x;
                num[markn]=x;
                marks++,markn++;
            }
        }
        if(k%3<2){
           int x=move(k,k+1,parent[i]);
           if(check(x)==-1){
                son[marks]=x;
                num[markn]=x;
                marks++,markn++;
            }
        }
        if(k>2){
            int x=move(k,k-3,parent[i]);
           if(check(x)==-1){
                son[marks]=x;
                num[markn]=x;
                marks++,markn++;
            }
        }
        if(k<6){
            int x=move(k,k+3,parent[i]);
            if(check(x)==-1){
                son[marks]=x;
                num[markn]=x;
                marks++,markn++;
            }
        }
    }
        memcpy(parent,son,sizeof(son));
        markp=marks;

        bfs();
}
int main(){
    memset(num,0,sizeof(num));
    memset(num1,0,sizeof(num1));
    int i;
    for(i=0;i<9;i++)scanf("%d",&temp[i]);
    num[0]=hash(temp);
    parent[0]=hash(temp);
    num1[0]=876543210;
    parent1[0]=876543210;
    markn++;
    markn1++;
    markp++;
    markp1++;
    bfs();
    printf("%d",step);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值