题目链接:P1379 八数码难题
题解: 学习A*可以参考这里点这 ,自我评价A*算法是在基础的BFS上引入估值函数的概念,给予BFS中每个点一个类似最短路的距离权值,然后利用优先队列实现对BFS求路径的优化,(就很像是巧妙的基于bfs中点权,再像求最短路中迪杰斯特拉的堆优化一样进行优化),本题中利用距离起点已走步数作为G值,和最终状态的差距作为H值,更加F=H+G用优先队列维护,每次对F较小的先搜索并更新,因为是字符串表示状态,可以用map记录是否访问过和距离起点距离
细节见注释
#include<iostream>
#include<stack>
#include<list>
#include<set>
#include<vector>
#include<algorithm>
#include<math.h>
#include<numeric>
#include<map>
#include<cstring>
#include<queue>
#include<iomanip>
#include<cmath>
#include<queue>
#include <bitset>
#include<unordered_map>/*
#ifndef local
#define endl '\n'
#endif */
#define mkp make_pair
using namespace std;
using std::bitset;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll MAXN=2e6+10;
const ll N=2e5+100;
const ll mod=1e9+7;
const ll hash_p1=1610612741;
const ll hash_p2=805306457;
const ll hash_p3=402653189;
//-----------------------------------------------------------------------------------------------------------------*/
// ll head[MAXN],net[MAXN],to[MAXN],edge[MAXN]/*流量*/,cost[MAXN]//费用;
/*
void add(ll u,ll v,ll w,ll s){
to[++cnt]=v;net[cnt]=head[u];edge[cnt]=w;cost[cnt]=s;head[u]=cnt;
to[++cnt]=u;net[cnt]=head[v];edge[cnt]=0;cost[cnt]=-s;head[v]=cnt;
}
struct elemt{
int p,v;
};
-----------------------------------
求[1,MAXN]组合式和逆元
ll mi(ll a,ll b){
ll res=1;
while(b){
if(b%2){
res=res*a%mod;
}
a=a*a%mod;
b/=2;
}
return res;
}
ll fac[MAXN+10],inv[MAXN+10]
ll C(int m,int n){//组合式C(m,n);
if(!n){
return 1;
}
return fac[m]*(inv[n]*inv[m-n]%mod)%mod;
}
fac[0]=1;inv[0]=1;
for(ll i=1;i<=MAXN;i++){
fac[i]=(fac[i-1]*i)%mod;
inv[i]=mi(fac[i],mod-2);
}
---------------------------------
unordered_map<int,int>mp;
//优先队列默认小顶堆 , greater<int> --小顶堆 less<int> --大顶堆
priority_queue<elemt,vector<elemt>,comp>q;
struct comp{
public:
bool operator()(elemt v1,elemt v2){
return v1.v<v2.v;
}
};
set<int>::iterator it=st.begin();
*/
//emplace_back() 等于push_back(),但效率更高,传输pair时emplace_back(i,j)==push_back({i,j})
// vector<vector<int>>edge; 二维虚拟储存坐标
//-----------------------------------------------------------------------------------------------------------------*/
//map<int,bool>mp[N];
//emplace_back()
string key="123804765";//目标状态
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int h(string s){//距离终点的状态差数(粗略的来代表距离终点的距离)
int res=0;
for(int i=0;i<9;i++){
if(s[i]!=key[i]){
res++;
}
}
return res;
}
struct elemt{
int g,h;//分别代表距离起点距离,和到达终点所需状态差数量
string s;//当前状态
int x,y;//记录0点位置
bool operator < (const elemt &v)const{//按F=G+H排,优先选F小的,F相同选H小的
if(g+h==v.g+v.h){
return h>v.h;
}
return g+h>v.g+v.h;
}
};
priority_queue<elemt>q;//优先队列
map<string,bool>mp;
map<string,int>dis;
int A_STAR(elemt s){
while(q.size()){
q.pop();
}
q.push(s);
while(q.size()){
elemt f=q.top();
if(f.s==key){//走到了目标状态,返回
return f.g;
}
q.pop();
int pre=f.x*3+f.y-4;//原0的下标
for(int i=0;i<4;i++){//四个转换方向
int fx=f.x+dx[i],fy=f.y+dy[i];
int tmp=fx*3+fy-4;//换位后0的下标
if(fx>=1&&fx<=3&&fy>=1&&fy<=3){
swap(f.s[pre],f.s[tmp]);//更新换位后状态
if(mp[f.s]==0||mp[f.s]==1&&f.g+1<dis[f.s]){//尝试更新(BFS最短路经典部分)
dis[f.s]=f.g+1;
mp[f.s]=1;
q.push({f.g+1,h(f.s),f.s,fx,fy});
}
swap(f.s[pre],f.s[tmp]);//恢复状态
}
}
}
}
int main(){
/*cout<<setiosflags(ios::fixed)<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(不含整数部分)*/
/*cout<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(含整数部分)*/
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//同步流
string s;
cin>>s;
elemt d;
d.s=s;
d.g=0;
d.h=0;
for(int i=0;i<9;i++){
if(s[i]=='0'){
d.x=i/3+1;
d.y=i%3+1;
break;
}
}
cout<<A_STAR(d)<<endl;
return 0;
}