您的位置:首页 > 其它

历届试题 九宫重排

2017-05-22 21:23 267 查看
问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。





  我们把第一个图的局面记为:12345678.

  把第二个图的局面记为:123.46758

  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。

  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.

123.46758

样例输出

3

样例输入

13524678.

46758123.

样例输出

22

set去重复,很费时间,但是没超时

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<ctime>
using namespace std;
char star[5][5] ={0};
char end[5][5] = {0};
int dir[4][2]={1,0,0,1,-1,0,0,-1};
typedef struct node{
int x, y;
int pre;
long long step;
char map[5][5];//保存每一次的状态
}NO;
queue<NO>q;
set<string>hsh;

bool check(NO n){
for(int i = 0; i < 3; i ++){
for(int j = 0; j < 3; j++){
if(n.map[i][j]!=end[i][j])
return false ;
}
}
return true;
}

bool getvis(NO a){
string emp="";
for(int i = 0; i < 3; i ++){
for(int j = 0; j < 3; j ++)
emp+=a.map[i][j];
}
if(hsh.find(emp)!=hsh.end())//说明set中已经存在emp
return false;
hsh.insert(emp);//如果不存在则插入
return true;
}

bool bfs(int x, int y){//广搜

//q.push((NO){x,y,0,'X',(NO.map)star});
int i,s,t;
NO no ;
no.x = x;
no.y = y;
no.pre=-1;
no.step=0;
for(i = 0; i < 3; i++){
for(int j = 0; j < 3; j ++)
no.map[i][j]=star[i][j];
}
q.push(no);
while(!q.empty()){
NO f = q.front();
q.pop();
if(check(f)){//判断是否到达最终状态
printf("%lld\n",f.step);
return true;
}

for(i = 0; i < 4; i ++){
NO f1 = f;
s = f1.x + dir[i][0];
t = f1.y + dir[i][1];
if(f1.pre==0&&i==2)//判断方向,因为如果上一步往上走,并且下一步往下走一定是重复情况
continue;
if(i==0&&f1.pre==2)
continue;
if(f1.pre==1&&i==3)
continue;
if(i==3&&f1.pre==1)
continue;

if(s>=0&&s<3&&t>=0&&t<3){//判断边界
//交换
swap(f1.map[s][t], f1.map[f1.x][f1.y]);
f1.x=s;
f1.y=t;
f1.step++;
f1.pre=i;
if(getvis(f1)){//判重
if(check(f1)){//判断是否到达最终状态
printf("%lld\n",f1.step);
return true;
}
q.push(f1);
}

}
}

}

return false;
}

int main(){
int x,y;
for(int i=0;i<3;i++){
for(int j = 0; j < 3; j ++){
scanf("%c", &star[i][j]);
if(star[i][j]=='.'){
x=i;
y=j;
}
}
}
getchar();//接收多余的回车符
for(int i=0;i<3;i++){
for(int j = 0; j < 3; j ++){
scanf("%c", &end[i][j]);
}
}

if(!bfs(x,y))//无法到达最终状态
printf("-1\n");

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: