Eight
Time Limit : 10000/5000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 15 Accepted Submission(s) : 2
Special Judge
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12 13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x r-> d-> r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
第一次接觸A* 寫得太想吐了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#define inf 1<<30
#define eps 1e-7
#define LD long double
#define LL long long
#define maxn 1000000005
using namespace std;
const int ed=322560;
int Hash[9]= {1,1,2,6,24,120,720,5040,40320};
struct node
{
int Map[3][3];
int h,g;
int x,y;
int Hash;
bool operator<(const node n1)const //優先隊列第一關鍵字爲h,第二關鍵字爲g
{
return h!=n1.h?h>n1.h:g>n1.g;
}
bool cheak()
{
if(x>=0&&x<3&&y>=0&&y<3)
return true ;
return false ;
}
} u,v;
int vis[400000];
int pri[400000];
int dir[4][2]= {0,1,0,-1,1,0,-1,0};
bool ok(node tmp) //判斷狀態是否合法 逆序數爲偶數
{
int a[9],k=0;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
a[k++]=tmp.Map[i][j];
int ans=0;
for(int i=0; i<k; i++)
for(int j=i+1; j<k; j++)
if(a[i]&&a[j]&&a[i]>a[j])
ans++;
return (ans&1);
}
int get_hash(node tmp) //獲得康拓值
{
int ans=0;
int a[9],k=0;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
a[k++]=tmp.Map[i][j];
for(int i=0; i<k; i++)
{
int sum=0;
for(int j=0; j<i; j++)
if(a[j]>a[i])
sum++;
ans+=Hash[i]*sum;
}
return ans;
}
int get_h(node tmp) //估價函數 每一個點移動到原來地方的最短路程和 曼哈頓距離
{
int ans;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
if(tmp.Map[i][j])
ans+=abs(i-(tmp.Map[i][j]-1)/3)+abs(j-(tmp.Map[i][j]-1)%3);
return ans;
}
void print()
{
string str;
str.clear();
int st=ed;
while(pri[st]!=-1)
{
if(vis[st]==0)
{
str+='r';
}
else if(vis[st]==1)
{
str+='l';
}
else if(vis[st]==2)
{
str+='d';
}
else
str+='u';
st=pri[st];
}
for(int i=str.size()-1;i>=0;i--)
cout<<str[i];
cout<<endl;
return ;
}
void bfs()
{
priority_queue<node >q;
q.push(u);
memset(vis,-1,sizeof(vis));
memset(pri,-1,sizeof(pri));
vis[u.Hash]=-2;
while(!q.empty())
{
//cout<<q.size()<<endl;
u=q.top();
q.pop();
for(int i=0; i<4; i++)
{
v=u;
v.x+=dir[i][0];
v.y+=dir[i][1];
if(v.cheak())
{
swap(v.Map[v.x][v.y],v.Map[u.x][u.y]);
v.Hash=get_hash(v);
if(vis[v.Hash]==-1&&!ok(v))
{
v.h=get_h(v);
v.g++;
vis[v.Hash]=i;
pri[v.Hash]=u.Hash;
q.push(v);
}
}
if(v.Hash==ed)
{
print();
return ;
}
}
}
}
int main()
{
char ch[100];
memset(ch,0,sizeof(ch));
while(cin>>ch[0])
{
for(int i=1; i<9; i++)
cin>>ch[i];
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
if(ch[i*3+j]=='x')
{
u.Map[i][j]=0;
u.x=i;
u.y=j;
u.Hash=get_hash(u);
u.h=get_h(u);
u.g=0;
}
else u.Map[i][j]=ch[i*3+j]-'0';
}
}
if(u.Hash==ed)
{
cout<<endl;
continue ;
}
if(!ok(u))
bfs();
else cout<<"unsolvable"<<endl;
}
}