Eleven puzzle
Time Limit: 20000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 531 Accepted Submission(s): 135
Problem Description
Partychen invents a new game named “Eleven Puzzle” .Just like the classic game “Eight Puzzle”,but there some difference between them:The shape of the board is different and there are two empty tiles.
The tile in black means it’s empty
Each step you can move only one tile.
Here comes the problem.How many steps at least it required to done the game.
Input
The first line of input contains one integer specifying the number of test cases to follow.
Every case contains five lines to describe the initial status of the board. 0 means empty.
It’s confirmed that the board is legal.
Output
Output one line for each testcase.Contain an integer denotes the minimum step(s) it need to complete the game.Or “No solution!” if it’s impossible to complete the game within 20 steps.
Sample Input
3
2
1 0 3
4 5 6 7 8
9 0 11
10
0
1 2 3
4 5 6 7 8
9 10 11
0
0
11 10 9
8 7 6 5 4
3 2 1
0
Sample Output
题意:
给出一个如图的图形,要求用最小的步数变化成右图图形
分析:
如果单向搜索,无论是从终状态还是从开始状态都会直接超时,计算次数为4^20 > 10^8
那么此时应该考虑双向搜索,即队列中同时保存终状态的状态转移和开始状态的状态转移,每一种状态bfs10步,当两端相撞时得到结果,计算次数 4^10
我用的map做状态映射,效果并不差 156ms
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
long long d[30];
int g[5][5];
struct node
{
int g[5][5];
int step;
int x1,y1;
int x2,y2;
} p1;
map<long long ,int >mp[2];
queue<node>que;
int dir[][5]= {{0,1},{0,-1},{1,0},{-1,0}};
bool inbound(node k,int x,int y)
{
if(x>=0&&x<5&&y>=0&&y<5)
{
if(k.g[x][y]==INF||k.g[x][y]==12) return false;
else return true;
return false;
}
return false;
}
long long getval(node k)
{
long long sum=0;
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
if(k.g[i][j]!=INF)
{
if(k.g[i][j]/10) sum=sum*100+k.g[i][j];
else sum=sum*10+k.g[i][j];
}
}
}
return sum;
}
void bfsx(int flag)
{
mp[flag].clear();
node k;
while(!que.empty()) que.pop();
que.push(p1);
mp[flag][getval(p1)]=1;
while(!que.empty())
{
k=que.front();
que.pop();
long long pri=getval(k);
if(flag)
{
if(mp[0][pri])
{
if(mp[0][pri]+k.step-2<=20)
{
printf("%d\n",mp[0][pri]+k.step-2);
return ;
}
else continue;
}
}
for(int i=0; i<4; i++)
{
node temp=k;
int s=temp.x1+dir[i][0];
int t=temp.y1+dir[i][1];
if(inbound(temp,s,t))
{
temp.step++;
if(temp.step>12&&!flag) continue;
else if(temp.step>10&&flag) continue;
swap(temp.g[temp.x1][temp.y1],temp.g[s][t]);
long long pri=getval(temp);
if(mp[flag][pri]) continue;
mp[flag][pri]=temp.step;
temp.x1=s,temp.y1=t;
que.push(temp);
}
}
for(int i=0; i<4; i++)
{
node temp=k;
int s=temp.x2+dir[i][0];
int t=temp.y2+dir[i][1];
if(inbound(temp,s,t))
{
temp.step++;
if(temp.step>12&&!flag) continue;
else if(temp.step>10&&flag) continue;
swap(temp.g[temp.x2][temp.y2],temp.g[s][t]);
long long pri=getval(temp);
if(mp[flag][pri]) continue;
mp[flag][pri]=temp.step;
temp.x2=s,temp.y2=t;
que.push(temp);
}
}
}
if(flag) printf("No solution!\n");
}
int main()
{
memset(g,0x3f,sizeof g);
g[0][2]=12;
g[1][1]=1,g[1][2]=2,g[1][3]=3;
g[2][0]=4,g[2][1]=5,g[2][2]=6,g[2][3]=7,g[2][4]=8;
g[3][1]=9,g[3][2]=10,g[3][3]=11;
g[4][2]=12;
memcpy(p1.g,g,sizeof g);
p1.x1=0,p1.y1=2;
p1.x2=4,p1.y2=2;
p1.step=1;
bfsx(0);
int T;
scanf("%d",&T);
while(T--)
{
memset(g,0x3f,sizeof g);
for(int i=0; i<5; i++)
{
if(i==0||i==4) scanf("%d",&g[i][2]);
else if(i==1||i==3) for(int j=1; j<=3; j++) scanf("%d",&g[i][j]);
else for(int j=0; j<5; j++) scanf("%d",&g[i][j]);
}
int flag=0;
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
if(g[i][j]==0)
{
g[i][j]=12;
if(!flag) p1.x1=i,p1.y1=j;
else p1.x2=i,p1.y2=j;
flag=1;
}
}
}
memcpy(p1.g,g,sizeof g);
p1.step=1;
bfsx(1);
}
return 0;
}