历届试题 九宫重排
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;
}
如下面第一个图的九宫格中,放着 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;
}
相关文章推荐
- 蓝桥杯 历届试题 九宫重排(bfs)
- 蓝桥杯-历届试题-九宫重排-BFS+剪枝
- 蓝桥杯 历届试题 九宫重排 解题报告(BFS,双向BFS优化)
- 历届试题 九宫重排
- [蓝桥杯][历届试题]九宫重排
- 蓝桥杯 历届试题 九宫重排
- 蓝桥杯 历届试题 九宫重排 (广搜)
- 蓝桥网 历届试题 九宫重排
- 算法笔记_183:历届试题 九宫重排(Java)
- 蓝桥杯 历届试题 九宫重排
- 蓝桥杯 历届试题 九宫重排 BFS Java
- 蓝桥杯【历届试题】九宫重排
- 蓝桥杯历届试题——九宫重排(bfs)
- 蓝桥杯历届试题——九宫重排(启发式搜索)
- 蓝桥杯 历届试题-九宫重排
- 蓝桥杯 历届试题 九宫重排 (八数码问题--康托展开去重 + bfs搜索)
- 蓝桥杯, 历届试题 九宫重排 (八数码)
- 蓝桥杯历届试题 九宫重排(输入输出方式选择)
- 蓝桥杯 历届试题 九宫重排(双向搜索优化)
- 历届试题 九宫重排 蓝桥杯