这种鲜明的玄学风格很明显就是十几年前的题目。

Description

  在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务。

  

Input

  第一行有一个正整数T,表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

Output

  对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

Sample Input

  2
  10110
  01*11
  10111
  01001
  00000
  01011
  110*1
  01110
  01010
  00100

Sample Output

  7
  -1

HINT

  T<=10。

Solution

  拿到这道题应该没有别的想法吧,于是我们直接开始往搜索去想。

  由于步数最多只有15,所以最暴力的暴力的时间复杂度为O(T*25*815)。

  如果用A*算法解决这道题,估价函数为不符合答案的格子个数,如果剩余步数小于这个值,那么这个状态一定不能在15步内走到答案。

  复杂度似乎可以不用乘上25,所以理论时间复杂度上限为O(T*815)。

  所以A*算法就是这么神奇地通过该题的,网络上题解有很多,小C就不再赘述。

  都是玄学。

  所以小C还是介绍一下自己的折半搜索做法吧。

  从目标状态往前搜8步,用一个map把每个状态hash的答案存下来。

  从每个起始状态往后搜7步,对于每个状态到map查找并更新答案。

  理论时间复杂度O(25*88*log(state)+T*25*87*log(state))。

  加一个判重的剪枝,可以跑得飞快。

  map还可以用O(1)的,hash还可以动态维护。所以时间复杂度可以优化到O(88+T*87)。

  而且每个状态不是满的8种转移方式,实际的时间复杂度远远小于上限。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define ll unsigned long long
using namespace std;
typedef char matr[][];
const int fx[][]={{,},{,-},{-,},{-,-},{,},{,-},{-,},{-,-}};
map <ll,int> mp;
matr c,d;
int cx,cy,dx,dy,ans,t; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} ll geth(matr c,int x,int y)
{
ll h=;
register int i,j;
for (i=;i<=;++i)
for (j=;j<=;++j) h=h*+c[i][j]-'';
h=h*+x-; h=h*+y-;
return h;
} bool check(int x,int y) {return x<||x>||y<||y>;} void dfs1(int stp)
{
ll h=geth(c,cx,cy);
if (mp[h]&&mp[h]<=stp) return;
mp[h]=stp;
if (stp>) return;
register int i,ncx,ncy;
for (i=;i<;++i)
{
ncx=cx+fx[i][];
ncy=cy+fx[i][];
if (check(ncx,ncy)) continue;
swap(c[cx][cy],c[ncx][ncy]);
swap(cx,ncx); swap(cy,ncy);
dfs1(stp+);
swap(cx,ncx); swap(cy,ncy);
swap(c[cx][cy],c[ncx][ncy]);
}
} void dfs2(int stp)
{
ll h=geth(d,dx,dy);
if (mp[h]) ans=min(ans,stp+mp[h]-);
if (stp>) return;
register int i,ndx,ndy;
for (i=;i<;++i)
{
ndx=dx+fx[i][];
ndy=dy+fx[i][];
if (check(ndx,ndy)) continue;
swap(d[dx][dy],d[ndx][ndy]);
swap(dx,ndx); swap(dy,ndy);
dfs2(stp+);
swap(dx,ndx); swap(dy,ndy);
swap(d[dx][dy],d[ndx][ndy]);
}
} int main()
{
register int i,j;
t=read();
for (i=;i<=;++i)
for (j=;j<=;++j)
if (i<j||i==j&&i<=) c[i][j]='';
else if (i>j||i==j&&i>=) c[i][j]='';
cx=cy=; dfs1();
while (t--)
{
ans=;
for (i=;i<=;++i) scanf("%s",d[i]+);
for (i=;i<=;++i)
{
for (j=;j<=;++j)
if (d[i][j]=='*') {dx=i; dy=j; d[i][j]=''; break;}
if (j<=) break;
}
dfs2();
printf("%d\n",ans==?-:ans);
}
}

Last Word

  不过仔细想想玄学题目并不只是十几年前的专利啊,比如FJOI的D2T2……

[BZOJ]1085 骑士精神(SCOI2005)的更多相关文章

  1. bzoj 1085骑士精神

    bzoj 1085骑士精神 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2 ...

  2. A*算法详解 BZOJ 1085骑士精神

    转载1:A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算 ...

  3. bzoj 1085骑士精神 迭代深搜

    题目传送门 题目大意:给出一幅棋盘,问能否复原,中文题面,不做解释. 思路:第一次写迭代深搜的题目,这道题还是挺经典的.这道题的状态很明显的每多搜一层就是多八倍,非常的多,而且又是t组输入,所以必定有 ...

  4. BZOJ 1085 骑士精神 迭代加深搜索+A*

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1085 题目大意: 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个 ...

  5. [bzoj] 1085 骑士精神 || ID-DFS

    原题 找到最少的步数成为目标状态. IDDFS(限制层数的dfs)即可 #include<cstdio> #include<algorithm> using namespace ...

  6. BZOJ 1085 / LOJ 2151 [SCOI2005]骑士精神 (剪枝/A*迭代搜索)

    题目大意:略 直接爆搜会T,我们优化一下,统计出当前棋盘和目标棋盘不同的位置的数量k,那么当前棋盘变成目标棋盘最少的移动次数是k-1 每次选择一个最大深度ma,那么如果当前走了dep步,显然必须保证d ...

  7. 『骑士精神 IDA*』

    骑士精神(SCOI2005) Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵 ...

  8. Bzoj 1085: [SCOI2005]骑士精神 (dfs)

    Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...

  9. BZOJ 1085: [SCOI2005]骑士精神( IDDFS + A* )

    一开始写了个 BFS 然后就 T 了... 这道题是迭代加深搜索 + A* -------------------------------------------------------------- ...

随机推荐

  1. 服务器数据恢复_服务器xfs数据丢失数据恢复

    简介:太原一家公司的服务器出现故障,服务器是linux服务器,连接了一台某型号的存储,文件系统为xfs文件系统.管理员使用xfs_repair工具试图对文件系统进行修复但修复失败,linux服务器中所 ...

  2. [译]RabbitMQ教程C#版 - 工作队列

    先决条件 本教程假定RabbitMQ已经安装,并运行在localhost标准端口(5672).如果你使用不同的主机.端口或证书,则需要调整连接设置. 从哪里获得帮助 如果您在阅读本教程时遇到困难,可以 ...

  3. mysql数据库基本操作

    下载地址 http://www.mysql.com/downloads/mysql/ 端口号:3306 用户名:root 密码:自定义 连接到MySQL服务器 >mysql -uroot -pr ...

  4. 优化从 App.config 读取配置文件

    public class AppSettingsConfig { /// <summary> ////// </summary> public static int Query ...

  5. GZip 压缩及解压缩

    /// <summary> /// GZipHelper /// </summary> public class GZipHelper { /// <summary> ...

  6. 4-51单片机WIFI学习(开发板51单片机自动冷启动下载原理)

    上一篇链接 http://www.cnblogs.com/yangfengwu/p/8743936.html 这一篇说一下自己板子的51单片机自动冷启动下载原理,我挥舞着键盘和鼠标,发誓要把世界写个明 ...

  7. ELK学习总结(2-5)elk的版本控制

    ----------------------------------------------------------------- 1.悲观锁和乐观锁 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据 ...

  8. JS解析JSON字符串

    问题描述:后台需要传递给前台一些数据,用于页面数据显示,因为是一些Lable标签,所以数据传递到前台需要解析. 思路:因为数据比较杂乱,所以我选择传递的数据类型是Json格式,但是数据展示时需要解析成 ...

  9. Hibernate(五):Hibernate配置文件及C3P0的用法

    配置文件可配项: 参考文档:hibernate-release-5.2.9.Final/documentation/userguide/html_single/Hibernate_User_Guide ...

  10. 南京邮电大学java程序设计作业在线编程第二次作业

    王利国的"Java语言程序设计第2次作业(2018)"详细 作业结果详细 总分:100 选择题得分:60  1. 表达式9==8&&3<7的运算结果是( ) ...