题目:http://poj.org/problem?id=1077
大神原文链接:https://blog.csdn.net/dolfamingo/article/details/77825569
1.正向bfs;
2.反向bfs;
3.双向bfs;
4.A*
1.正向bfs:用数组队列,用stl里面的队列会超时
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
const int len=1e6+10;
using namespace std;
int f[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
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];
int front,rear;
struct node
{
int s[9];
int index;
int i;
}q[len];
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;
}
bool bfs(node ans)
{
memset(vis,0,sizeof(vis));
front=rear=0;
ans.index=kang(ans.s);
pre[ans.index]=-1;
vis[ans.index]=1;
q[rear++]=ans;
while(front!=rear)
{
node t=q[front++];
if(t.index==1) 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);
int h=temp.index;
if(!vis[h])
{
vis[h]=1;
pre[h]=t.index;
path[h]=p[i];
q[rear++]=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 ss[9];
node ans;
for(int i=0;i<9;i++) cin>>ss[i];
for(int i=0;i<9;i++)
{
if(ss[i]=='x') ans.i=i,ans.s[i]=9;
else ans.s[i]=ss[i]-'0';
}
if(bfs(ans)) print(1);
else printf("unsolvable\n");
return 0;
}
2:反向bfs:用数组队列,用stl里面的队列会超时
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define len 400000
using namespace std;
bool vis[len];
int f[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int dir[4][2]={ 0,1,0,-1,1,0,-1,0},pre[len],front,rear;
char p[4]={'l','r','u','d'},path[len];
struct node
{
int s[9];
int i;
int index;
}q[len];
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;
}
bool bfs(int k)
{
memset(vis,0,sizeof(vis));
node t,temp;
for(int i=0;i<9;i++) t.s[i]=i+1;
t.index=1;
t.i=8;
vis[t.index]=1;
pre[t.index]=-1;
front=rear=0;
q[rear++]=t;
while(front!=rear)
{
temp=q[front++];
if(temp.index==k) return 1;
int x=temp.i/3;
int y=temp.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;
t=temp;
t.i=xx*3+yy;
swap(t.s[t.i],t.s[temp.i]);
t.index=kang(t.s);
int h=t.index;
if(!vis[h])
{
vis[h]=1;
pre[h]=temp.index;
path[h]=p[i];
q[rear++]=t;
}
}
}
return 0;
}
int main()
{
char s[10];
node ans;
for(int i=0;i<9;i++) cin>>s[i];
for(int i=0;i<9;i++)
{
if(s[i]=='x') ans.i=i,ans.s[i]=9;
else ans.s[i]=s[i]-'0';
}
ans.index=kang(ans.s);
int k=ans.index;
if(bfs(k))
{
while(pre[k]!=-1) printf("%c",path[k]),k=pre[k];
printf("\n");
}
else printf("unsolvable\n");
return 0;
}
3:双向队列,用stl队列(数组队列也行)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define len 400000
using namespace std;
bool vis1[len],vis2[len];
int f[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int dir1[4][2]={{-1, 0},{1,0},{0,-1},{0, 1}},pre1[len];
int dir2[4][2]={{0,1},{0,-1},{1,0},{-1,0}},pre2[len];
char p1[4]={'u','d','l','r'},path1[len];
char p2[4]={'l','r','u','d'},path2[len];
struct node
{
int s[9];
int index;
int i;
}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 bfs()
{
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
ans.index=kang(ans.s);
vis1[ans.index]=1;
pre1[ans.index]=-1;
queue<node> q1;
q1.push(ans);
for(int i=0;i<9;i++) ans.s[i]=i+1;
ans.index=1;
ans.i=8;
vis2[ans.index]=1;
pre2[ans.index]=-1;
queue<node> q2;
q2.push(ans);
while(!q1.empty()||!q2.empty())
{
int s1=q1.size();
while(s1--)
{
node t=q1.front();
q1.pop();
if(vis2[t.index]) return t.index;
int x=t.i/3;
int y=t.i%3;
for(int i=0;i<4;i++)
{
int xx=x+dir1[i][0];
int yy=y+dir1[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);
int h=temp.index;
if(!vis1[h])
{
vis1[h]=1;
pre1[h]=t.index;
path1[h]=p1[i];
q1.push(temp);
}
}
}
int s2=q2.size();
while(s2--)
{
node t=q2.front();
q2.pop();
if(vis1[t.index]) return t.index;
int x=t.i/3;
int y=t.i%3;
for(int i=0;i<4;i++)
{
int xx=x+dir2[i][0];
int yy=y+dir2[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);
int h=temp.index;
if(!vis2[h])
{
vis2[h]=1;
pre2[h]=t.index;
path2[h]=p2[i];
q2.push(temp);
}
}
}
}
return 0;
}
void print1(int x)
{
char c[len];
int j=0;
while(pre1[x]!=-1)
{
c[j++]=path1[x];
x=pre1[x];
}
for(j--;j>=0;j--) printf("%c",c[j]);
}
void print2(int k)
{
while(pre2[k]!=-1)
{
printf("%c",path2[k]);
k=pre2[k];
}
printf("\n");
}
int main()
{
char ss[9];
for(int i=0;i<9;i++) cin>>ss[i];
for(int i=0;i<9;i++)
{
if(ss[i]=='x') ans.i=i,ans.s[i]=9;
else ans.s[i]=ss[i]-'0';
}
int k=bfs();
if(k!=0) print1(k),print2(k);
else printf("unsolvable\n");
return 0;
}
4.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;
}