两种方法都是曼哈顿法
迭代加深采用dfs,为了防止爆栈。
A*采用bfs
迭代加深(IDA*)
#include<bits/stdc++.h>
using namespace std;
#define N 4
#define N2 16
#define LIMIT 100
int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0}; //注意这块有的数据可能因为走的方向不同而导致TLE
char dir[4]={'r','u','l','d'};
int MDT[N2][N2];
struct Puzzle{
int f[N2],space,MD;
};
Puzzle state;
int limit;
int path[LIMIT];
struct State{
Puzzle puzzle;
int estimated;
bool operator < (const State &s) const{
return estimated>s.estimated;
}
};
int getallMD(Puzzle pz){
int sum=0;
for(int i=0;i<N2;i++){
if(pz.f[i]==N2) continue;
sum+=MDT[i][pz.f[i]-1];
}
return sum;
}
bool isSolved(){
for(int i=0;i<N2;i++){
if(state.f[i]!=i+1) return false;
}return true;
}
bool dfs(int depth,int pre){
if(state.MD==0) return 1;
if(depth+state.MD>limit) return false;
int sx=state.space/N;
int sy=state.space%N;
Puzzle tmp;
for(int r=0;r<4;r++){
int tx=sx+dx[r];
int ty=sy+dy[r];
if(tx<0||ty<0||tx>=N||ty>=N)
continue;
if(max(pre,r)-min(pre,r)==2) continue;//去重
tmp=state;
state.MD-=MDT[tx*N+ty][state.f[tx*N+ty]-1];
state.MD+=MDT[sx*N+sy][state.f[tx*N+ty]-1];
swap(state.f[sx*N+sy],state.f[tx*N+ty]);
state.space=tx*N+ty;
if(dfs(depth+1,r)){
path[depth]=r;
return true;
}
state=tmp;
}
return false;
}
string iterative_deepening(Puzzle in)
{
in.MD=getallMD(in);//初始状态的曼哈顿距离
for(limit=in.MD;limit<=LIMIT;limit++){
state=in;
if(dfs(0,-100)){
string ans="";
for(int i=0;i<limit;i++){
ans+=dir[path[i]];
}
return ans;
}
}
return "unsolvable";
}
int main(){
for(int i=0;i<N2;i++){
for(int j=0;j<N2;j++){
MDT[i][j]=abs(i/N-j/N)+abs(i%N-j%N);
}
}
Puzzle in;
for(int i=0;i<N2;i++){
cin>>in.f[i];
if(in.f[i]==0){
in.f[i]=N2;
in.space=i;
}
}
string ans=iterative_deepening(in);
cout<<ans.size()<<endl;
return 0;
}
A*
A*算法的详细介绍:
https://www.cnblogs.com/zhoug2020/p/3468167.html
#include<bits/stdc++.h>
using namespace std;
#define N 4
#define N2 16
int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0}; //注意这块有的数据可能因为走的方向不同而导致TLE
char dir[4]={'r','u','l','d'};
int MDT[N2][N2];
struct Puzzle{
int f[N2],space,MD;
int cost;
bool operator < (const Puzzle& p) const {
for(int i=0;i<N2;i++){
if(f[i]==p.f[i]) continue;
return f[i]<p.f[i];
}
return false;
}
};
struct State{
Puzzle puzzle;
int estimated;
bool operator < (const State &s) const{
return estimated>s.estimated;
}
};
int getallMD(Puzzle pz){
int sum=0;
for(int i=0;i<N2;i++){
if(pz.f[i]==N2) continue;
sum+=MDT[i][pz.f[i]-1];
}
return sum;
}
int astar(Puzzle s){
priority_queue<State> PQ;
s.MD=getallMD(s);
s.cost=0;
map<Puzzle,bool> V;
Puzzle u,v;
State initial;
initial.puzzle =s;
initial.estimated=getallMD(s);
PQ.push(initial);
while(!PQ.empty()){
State st=PQ.top(); PQ.pop();
u=st.puzzle;
if(u.MD==0) return u.cost;
V[u]=true;
int sx=u.space/N;
int sy=u.space%N;
for(int r=0;r<4;r++){
int tx=sx+dx[r];
int ty=sy+dy[r];
if(tx<0||ty<0||tx>=N||ty>=N){
continue;
}
v=u;
v.MD-=MDT[tx*N+ty][v.f[tx*N+ty]-1];
v.MD+=MDT[sx*N+sy][v.f[tx*N+ty]-1];
swap(v.f[sx*N+sy],v.f[tx*N+ty]);
v.space=tx*N+ty;
if(!V[v]){
v.cost++;
State news;
news.puzzle=v;
news.estimated=v.cost+v.MD;
PQ.push(news);
}
}
}
return -1;
}
int main()
{
for(int i=0;i<N2;i++){
for(int j=0;j<N2;j++){
MDT[i][j]=abs(i/N-j/N)+abs(i%N-j%N);
}
}
Puzzle in;
for(int i=0;i<N2;i++){
cin>>in.f[i];
if(in.f[i]==0){
in.f[i]=N2;
in.space=i;
}
}
cout<<astar(in)<<endl;
return 0;
}