题目:http://poj.org/problem?id=1077
参考大神原文链接:https://blog.csdn.net/dolfamingo/article/details/77825569
1:A*
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#define len 400000
using namespace std;
int f[]={ 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}},pre[len];
char p[4]={'u','d','l','r'},path[len];
bool vis[len];
struct node
{
int s[9];
int i,index;//i为x的位置
int f,g,h;
bool operator<(const node &a)
const{
if(a.f==f) return a.g<g;
else return a.f<f;
}
}ans;
int kang(int *a)
{
int t=8,sum=0;
for(int i=0;i<9;i++)
{
int s=0;
for(int j=i+1;j<9;j++) if(a[i]>a[j]) s++;
sum+=s*f[t-i];
}
return sum+1;
}
int dis(int *s)//曼哈顿距离:也就是某位置上的数字与目标位置差几步。
{
int sum=0;
for(int i=0;i<9;i++)
{
if(s[i]==9) continue;//
int x=i/3;//目的数组:123456789, 假设当前数组为;5432178x6
int y=i%3;//i为当前数字的下标,假设当前数字为5,下标为0,i=0,s[i]=5;
int xx=(s[i]-1)/3;//s[i]-1(数组下标从0开始)为目的位置,5应该在i=1,j=1位置上
int yy=(s[i]-1)%3;
sum+=abs(x-xx)+abs(y-yy);
}
return sum;
}
bool A_star(int k)
{
memset(vis,0,sizeof(vis));
ans.index=kang(ans.s);
ans.g=0;
ans.h=dis(ans.s);
ans.f=ans.g+ans.h;
pre[ans.index]=-1;
vis[ans.index]=1;
priority_queue<node> q;
q.push(ans);
while(!q.empty())
{
node t=q.top();
q.pop();
if(t.index==k) return 1;
int x=t.i/3;
int y=t.i%3;
for(int i=0;i<4;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx<0||xx>=3||yy<0||yy>=3) continue;
node temp=t;
temp.i=xx*3+yy;
swap(temp.s[temp.i],temp.s[t.i]);
temp.index=kang(temp.s);
temp.g++;
temp.h=dis(temp.s);
temp.f=temp.g+temp.h;
int h=temp.index;
if(!vis[h])
{
vis[h]=1;
pre[h]=t.index;
path[h]=p[i];
q.push(temp);
}
}
}
return 0;
}
void print(int x)
{
char c[len];
int j=0;
while(pre[x]!=-1)
{
c[j++]=path[x];
x=pre[x];
}
for(j--;j>=0;j--) printf("%c",c[j]);
printf("\n");
}
int main()
{
char s[10];
for(int i=0;i<9;i++) cin>>s[i];
for(int i=0;i<9;i++)
{
if(s[i]=='x') ans.s[i]=9,ans.i=i;
else ans.s[i]=s[i]-'0';
}
if(A_star(1)) print(1);
else printf("unsolvable\n");
return 0;
}
2:IDA*
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#define inf 2e6
#define len 100
using namespace std;
int f[]={ 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char p[4]={'u','d','l','r'},path[len];
struct node
{
int s[9];
int i;//i为x的位置
}ans;
int dis(int *s)//曼哈顿距离:也就是某位置上的数字与目标位置差几步。
{
int sum=0;
for(int i=0;i<9;i++)
{
if(s[i]==9) continue;//
int x=i/3;//目的数组:123456789, 假设当前数组为;5432178x6
int y=i%3;//i为当前数字的下标,假设当前数字为5,下标为0,i=0,s[i]=5;
int xx=(s[i]-1)/3;//s[i]-1(数组下标从0开始)为目的位置,5应该在i=1,j=1位置上
int yy=(s[i]-1)%3;
sum+=abs(x-xx)+abs(y-yy);
}
return sum;
}
bool IDA_star(node a,int step,int pre,int m)
{
if(dis(a.s)==0) return 1;
int x=a.i/3;
int y=a.i%3;
for(int i=0;i<4;i++)
{
if(i+pre==1||i+pre==5) continue;
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx<0||xx>=3||yy<0||yy>=3) continue;
node t=a;
t.i=xx*3+yy;
swap(t.s[t.i],t.s[a.i]);
path[step]=p[i];
if(step+1+dis(t.s)>m) continue;
if(IDA_star(t,step+1,i,m)) return 1;
}
return 0;
}
void print()
{
for(int i=0;i<strlen(path);i++) putchar(path[i]);
printf("\n");
}
int main()
{
char s[10];
for(int i=0;i<9;i++) cin>>s[i];
for(int i=0;i<9;i++)
{
if(s[i]=='x') ans.s[i]=9,ans.i=i;
else ans.s[i]=s[i]-'0';
}
int j;
for(j=0;j<=100;j++) if(IDA_star(ans,0,inf,j)) break;
if(j<=100) print();
else printf("unsolvable\n");
return 0;
}
改进IDA*
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#define inf 2e6
#define len 100
using namespace std;
int map[10];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char p[4]={'u','d','l','r'},path[len];
int h(int *s)//曼哈顿距离:也就是某位置上的数字的位置与目标位置差几步。
{
int sum=0;
for(int i=0;i<9;i++)
{
if(s[i]==9) continue;//
int x=i/3;//目的数组:123456789, 假设当前数组为;5432178x6
int y=i%3;//i为当前数字的下标,假设当前数字为5,下标为0,i=0,s[i]=5;
int xx=(s[i]-1)/3;//s[i]-1(数组下标从0开始)为目的位置,5应该在i=1,j=1位置上
int yy=(s[i]-1)%3;
sum+=abs(x-xx)+abs(y-yy);
}
return sum;
}
bool dfs(int g,int loc,int limit,int pre)
{
if(h(map)==0)
{
path[g]='\0';
return 1;
}
if(g+h(map)>limit) return 0;
int x=loc/3;
int y=loc%3;
for(int i=0;i<4;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(i+pre==5||i+pre==1) continue;方向与上一步相反, 剪枝
if(xx<0||xx>=3||yy<0||yy>=3) continue;
swap(map[loc],map[xx*3+yy]);
path[g]=p[i];
if(dfs(g+1,xx*3+yy,limit,i)) return 1;
swap(map[loc],map[xx*3+yy]);
}
return 0;
}
void print()
{
for(int i=0;path[i]!='\0';i++) printf("%c",path[i]);
printf("\n");
}
int main()
{
char s[10];
int loc;
for(int i=0;i<9;i++) cin>>s[i];
for(int i=0;i<9;i++)
{
if(s[i]!='x') map[i]=s[i]-'0';
else map[i]=9,loc=i;
}
int j;
for(j=1;j<=100;j++) if(dfs(0,loc,j,inf)) break;
if(j<=100) print();
else printf("unsolvable\n");
return 0;
}