BFS(A*)——八数码

在这里插入图片描述
在这里插入图片描述
相当于滑块拼图游戏

#include<bits/stdc++.h>
using namespace std;

int evaluate(string now)
{
    int value=0;
    for(int i=0;i<now.size();i++)
    {
        if(now[i]!='x')
        {
            int t=now[i]-'1';
            value+=abs(i/3-t/3)+abs(i%3-t%3);
        }
    }
    return value;
}
/*
012————i/3=0,i%3=i————(0,i)
345————(1,i)
678————(2,i)
*/
string bfs(string start)
{
    string ed="12345678x";//终点状态
    int dh[4]={-1,0,1,0},dl[4]={0,1,0,-1};//顺序是上右下左
    string option="urdl";
    unordered_map<string,int> dist;
    unordered_map<string,pair<string,char>>pre;//记录上一步的状态和执行的操作
    priority_queue<pair<int,string>,vector<pair<int,string> >,greater<pair<int,string> > >heap;
    //队列中存放状态以及该状态所有点到其终点的距离之和,使用小顶堆,使得估价值最小的方案先出队
    
    heap.push({evaluate(start),start});//初始状态入队
    dist[start]=0;
    
    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        
        string now=t.second;
        
        if(now==ed)break;
        int step=dist[now];
        int h,l;
        for(int i=0;i<now.size();i++)
        {
            if(now[i]=='x')
            {
                h=i/3,l=i%3;//当前可移动块的位置
                break;
            }
        }
                
        string p=now;//当now状态改变后,状态p即为now状态的上一步
        for(int i=0;i<4;i++)
        {
            int hh=h+dh[i],ll=l+dl[i];
            if(hh<0||hh>=3||ll<0||ll>=3)continue;
            swap(now[h*3+l],now[hh*3+ll]);//将当前可移动块与相邻拼图交换位置
            if(!dist.count(now)||dist[now]>step+1)
            {
                dist[now]=step+1;
                pre[now]={p,option[i]};//记录上个状态的选择
                heap.push({dist[now]+evaluate(now),now});
            }
            swap(now[h*3+l],now[hh*3+ll]);
        }
        
    }
    
    string op;
    while(ed!=start)
    {
        op+=pre[ed].second;
        ed=pre[ed].first;
    }
    reverse(op.begin(),op.end());
    return op;
}
int main()
{
    string str,temp;
    char ch;
    for(int i=0;i<9;i++)
    {
        cin>>ch;
        str+=ch;
        if(ch=='x')continue;
        temp+=ch;
    }
    int jg=0;
    for(int i=0;i<7;i++)
        for(int j=i+1;j<8;j++)
            if(temp[i]>temp[j])
                jg++;
    
    if(jg%2!=0)cout<<"unsolvable";
    else cout<<bfs(str);
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值