历届试题 九宫重排
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
思路:广搜
#include"iostream"
#include"cstring"
using namespace std;
int f[10],dis[360000],d[4][2]={1,0,-1,0,0,1,0,-1};
bool vis[368805];
typedef int State[9];
State st[364000],goal;
void ini()
{
f[0]=1;
for(int i=1;i<9;i++)
f[i]=f[i-1]*i;
}
bool visited(int x)
{
int code=0;
for(int i=0;i<9;i++)
{
int cnt=0;
for(int j=i+1;j<9;j++)
if(st[x][i]>st[x][j]) cnt++;
code+=cnt*f[8-i];
}
if(vis[code]) return false;
vis[code]=true;
return true;
}
int bfs()
{
ini();
int head=1,end=2;
dis[head]=0;
while(head<end)
{
State &a=st[head];
if(!memcmp(goal,a,sizeof(a))) return head;
int z;
for(z=0;z<9;z++) if(!a[z]) break;
int x=z/3,y=z%3;
for(int i=0;i<4;i++)
{
int newx=x+d[i][0],newy=y+d[i][1];
int newz=newx*3+newy;
if(newx>=0&&newx<3&&newy<3&&newy>=0)
{
State &t=st[end];
memcpy(&t,&a,sizeof(a));
swap(t[newz],t[z]);
dis[end]=dis[head]+1;
if(visited(end)) end++;
}
}
head++;
}
return 0;
}
int main()
{
char a[10];
cin>>a;
for(int i=0;i<strlen(a);i++)
if(a[i]=='.') goal[i]=0;
else goal[i]=a[i]-'0';
cin>>a;
for(int i=0;i<strlen(a);i++)
if(a[i]=='.') st[1][i]=0;
else st[1][i]=a[i]-'0';
int rst=bfs();
if(rst==0) cout<<"-1"<<endl;
else cout<<dis[rst]<<endl;
return 0;
}
详细记录
评测点序号 | 评测结果 | 得分 | CPU使用 | 内存使用 | 下载评测数据 |
---|---|---|---|---|---|
1 | 正确 | 20.00 | 0ms | 16.75MB | 输入 输出 |
2 | 正确 | 20.00 | 0ms | 16.74MB | VIP特权 |
3 | 正确 | 20.00 | 15ms | 16.74MB | VIP特权 |
4 | 正确 | 20.00 | 46ms | 16.74MB | VIP特权 |
5 | 正确 | 20.00 | 62ms | 16.74MB | VIP特权 |
推荐一个著名的OJ网站