Description

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

我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

Input

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

Output

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

Sample Input

样例输入1
12345678.
123.46758 样例输入2
13524678.
46758123.

Sample Output

样例输出1
3 样例输出2
22

Source

蓝桥杯
 
分析:暴力bfs会超时
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define INF 99999999
#define me(a,x) memset(a,x,sizeof(a))
int mon1[]= {,,,,,,,,,,,,};
int mon2[]= {,,,,,,,,,,,,};
int dir[][]= {{,},{,-},{,},{-,}};
int fac[] = {, , , , , , , , , };//i的阶乘 LL getval()
{
LL ret();
char c;
while((c=getchar())==' '||c=='\n'||c=='\r');
ret=c-'';
while((c=getchar())!=' '&&c!='\n'&&c!='\r')
ret=ret*+c-'';
return ret;
}
void out(int a)
{
if(a>)
out(a/);
putchar(a%+'');
}
int kt(int a[],int n)//康托展开
{
int ans=;
for(int i=;i<=n;i++)
{
int c=;
for(int j=i+;j<=n;j++)
{
if(a[j]<a[i])
c++;
}
ans+=(c*fac[n-i]);
}
return ans+;
} char str1[],str2[];
int a[][],b[][];
int sx,sy;
int t[];
int h;
int w;
bool vis[]; struct node
{
int x,y,step;//x,y代表空格位置
int c[][];//九宫格数组
node(int xx,int yy,int ss,int cc[][])//初始化
{
x=xx;
y=yy;
step=ss;
for(int i=; i<=; i++)
for(int j=; j<=; j++)
c[i][j]=cc[i][j];
}
int getkt()//得到结点数组的康托展开值
{
h=;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
t[h++]=c[i][j];
}
}
return kt(t,);
}
}; void init()//初始化
{
int cnt=;
for(int i=; i<=; i++)//得到原始九宫格
{
for(int j=; j<=; j++)
{
if(str1[cnt]=='.')
a[i][j]=,sx=i,sy=j;
else
a[i][j]=str1[cnt]-'';
cnt++;
}
}
cnt=;
for(int i=; i<=; i++)//得到目标九宫格
{
for(int j=; j<=; j++)
{
if(str2[cnt]=='.')
b[i][j]=;
else
b[i][j]=str2[cnt]-'';
cnt++;
}
}
me(vis,false);//九宫格状态数组
h=;
for(int i=;i<=;i++)//得到目标九宫格的康托展开值
{
for(int j=;j<=;j++)
{
t[h++]=b[i][j];
}
}
w=kt(t,);
}
int check(int x,int y)//边界约束
{
if(x<=&&x>=&&y<=&&y>=)
return ;
return ;
}
int bfs(int x,int y,int a[][])
{
queue<node> q; q.push(node(x,y,,a));
vis[node(x,y,,a).getkt()]=; while(!q.empty())
{
int x=q.front().x;
int y=q.front().y;
int step=q.front().step;
int c[][];
for(int i=; i<=; i++)
for(int j=; j<=; j++)
c[i][j]=q.front().c[i][j];
q.pop(); for(int i=; i<; i++)
{
int xx=x+dir[i][];
int yy=y+dir[i][];
int ss=step+; int cc[][];
if(check(xx,yy)==)//越界
continue; for(int i=; i<=; i++)
for(int j=; j<=; j++)
cc[i][j]=c[i][j];
cc[x][y]=cc[xx][yy];//移动
cc[xx][yy]=; if(vis[node(xx,yy,ss,cc).getkt()]==)//判断该状态的九宫格有没有搜索过
{
if(node(xx,yy,ss,cc).getkt()==w)//搜索到了目标
{
return ss;//返回步数
}
int temp=node(xx,yy,ss,cc).getkt(); vis[temp]=;//标记该状态的九宫格已经搜索过
q.push(node(xx,yy,ss,cc));
} }
}
return -;
}
int main()
{
while(~scanf("%s",str1))
{
scanf("%s",str2);
init(); int ans=bfs(sx,sy,a);
printf("%d\n",ans);
}
}

蓝桥杯 历届试题 九宫重排 (bfs+康托展开去重优化)的更多相关文章

  1. Java实现 蓝桥杯 历届试题 九宫重排

    问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...

  2. 算法笔记_183:历届试题 九宫重排(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成 ...

  3. 蓝桥杯OJ PREV-19 九宫重排

    题目描写叙述:   历届试题 九宫重排   时间限制:1.0s   内存限制:256.0MB        问题描写叙述 如以下第一个图的九宫格中,放着 1~8 的数字卡片.另一个格子空着.与空格子相 ...

  4. 蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索

    问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走 ...

  5. 2013年第四届蓝桥杯国赛 九宫重排(HashMap+双BFS优化)

    九宫重排     时间限制:1.0s   内存限制:256.0MB 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干 ...

  6. 蓝桥杯 历届试题 剪格子(dfs搜索)

    历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |* || +--****--+ ||* | ** ...

  7. 蓝桥杯 历届试题 网络寻路(dfs搜索合法路径计数)

    X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径 ...

  8. 蓝桥杯 历届试题 约数倍数选卡片 (经典数论+DFS)

    闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数.例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可 ...

  9. 蓝桥杯  历届试题 幸运数  dfs

    历届试题 幸运数 时间限制:1.0s   内存限制:256.0MB 问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的"筛法"生成 . 首先从1开始写出自然数1,2, ...

随机推荐

  1. query 中 radio选中小技巧

    在php中经常,经常要用到radio选中按钮,下次再登录时默认记录用户选中的选项,在PHP判断的时候: 在input中不能加checked=“<?php ;?>”:否则失效

  2. 一起来看看JavaScript中==和===有何不同

    '; // => true 如果其中一个值是true,则将其转换为1再进行比较.如果其中一个值是false,则将其转换为0再进行比较: true == 0; // => false fal ...

  3. ThinkPHP实现登陆功能

    思路:前台输入账号密码,后台自定义一个函数checkNamePwd()用于验证账号密码正确与否,在控制器里调用,其中,checkNamePwd()方法验证账号密码正确性是首先通过账号查找密码,然后把查 ...

  4. CSS参考手册

    CSS 属性 CSS 属性组: 动画 背景 边框和轮廓 盒(框) 颜色 内容分页媒体 定位 可伸缩框 字体 生成内容 网格 超链接 行框 列表 外边距 Marquee 多列 内边距 分页媒体 定位 打 ...

  5. 绑定Oracle Database 到 ActiveReport

    ActiveReport 可以和多种数据源交互,包括OLEDB, SQL, XML和集合对象. 在本文中我们将阐述如何绑定Oracle 数据库到 ActiveReport . 这是一件很轻松的事情.下 ...

  6. Express浅谈

    写给鸟自己的,大家如果不慎百度到这里来了,真好也在做这块功能,不懂的可以联系鸟.微信:jkxx123321 const Sequelize = require('sequelize'); const ...

  7. Array常用方法总结

    一.[常用语法] 1.1.数组的创建var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定 ...

  8. Prometheus Node_exporter 之 Network Netstat UDP

    Network Netstat UDP /proc/net/snmp 1. UDP In / Out type: GraphUnit: shortLabel: Datagrams out (-) / ...

  9. 多个div中的label标签对齐

    这是之前的页面效果: 添加红色部门的代码后: <head> <meta name="viewport" content="width=device-wi ...

  10. winform 关于Messagebox自动定时关闭

    添加一个类库MessageBoxTimeOut public class MessageBoxTimeOut { private string _caption; public void Show(s ...