题目描述

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

输入格式

第一行有一个正整数T(T<=10)T(T<=10)T(T<=10),表示一共有TTT组数据。接下来有TTT个5×55×55×5的矩阵,000表示白色骑士,111表示黑色骑士,∗*∗表示空位。两组数据之间没有空行。

输出格式

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

样例输入

222
101101011010110
01∗1101*1101∗11
101111011110111
010010100101001
000000000000000
010110101101011
110∗1110*1110∗1
011100111001110
010100101001010
001000010000100

样例输出

777
−1-1−1


听说正解是IDA∗IDA^*IDA∗,写IDA∗IDA^*IDA∗是不可能的,这辈子都不可能的,因此只能靠双向深搜+meetinthemiddle+meet\ in\ the\ middle+meet in the middle过日子了。
显然直接暴搜151515层会TLETLETLE,那么换个思路。
既然起点和终点都是已知的,不妨双向搜索,从起点搜888步,终点搜777步,在判断一下有没有可以拼起来的。
众所周知,深搜的状态数与层数成指数级增长,那么层数减半,状态数也就不会太多了 (实测只有几十万种)。
所以我们就可以放心大胆的搜了。
由于每个点至多只有333种取值,而总共只有252525个格子,因此可以直接用三进制表示整个矩阵 考试的时候用二维矩阵单哈直接冲突,嗯,难受。
将从终点出发的状态按照hashhashhash值为第一关键字,步数为第二关键字排序,之后每个从起点出发的状态就可以去这里面二分找最少的步数了 (懒得去重,所以直接找最左边的位置)。

CodeCodeCode

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_P1 = 500000;
const int MAX_P2 = 200000;
char s[10];
int map[10][10];
int a1_cnt, a2_cnt;
struct Node {ll val;int step;
} a1[MAX_P1], a2[MAX_P2];
bool operator<(const Node &a, const Node &b) {return a.val < b.val || a.val == b.val && a.step < b.step;
}
void dfs1(int x, int y, int step) {ll sum = 0;for(int i = 1; i <= 5; i++)for(int j = 1; j <= 5; j++)sum = sum * 3 + map[i][j];a1[++a1_cnt] = (Node){ sum, 8 - step };if(!step)return;x > 1 && y > 2 ? swap(map[x][y], map[x - 1][y - 2]), dfs1(x - 1, y - 2, step - 1), swap(map[x][y], map[x - 1][y - 2]), 0 : 0;x > 2 && y > 1 ? swap(map[x][y], map[x - 2][y - 1]), dfs1(x - 2, y - 1, step - 1), swap(map[x][y], map[x - 2][y - 1]), 0 : 0;x > 1 && y < 4 ? swap(map[x][y], map[x - 1][y + 2]), dfs1(x - 1, y + 2, step - 1), swap(map[x][y], map[x - 1][y + 2]), 0 : 0;x > 2 && y < 5 ? swap(map[x][y], map[x - 2][y + 1]), dfs1(x - 2, y + 1, step - 1), swap(map[x][y], map[x - 2][y + 1]), 0 : 0;x < 5 && y > 2 ? swap(map[x][y], map[x + 1][y - 2]), dfs1(x + 1, y - 2, step - 1), swap(map[x][y], map[x + 1][y - 2]), 0 : 0;x < 4 && y > 1 ? swap(map[x][y], map[x + 2][y - 1]), dfs1(x + 2, y - 1, step - 1), swap(map[x][y], map[x + 2][y - 1]), 0 : 0;x < 5 && y < 4 ? swap(map[x][y], map[x + 1][y + 2]), dfs1(x + 1, y + 2, step - 1), swap(map[x][y], map[x + 1][y + 2]), 0 : 0;x < 4 && y < 5 ? swap(map[x][y], map[x + 2][y + 1]), dfs1(x + 2, y + 1, step - 1), swap(map[x][y], map[x + 2][y + 1]), 0 : 0;
}
void dfs2(int x, int y, int step) {ll sum = 0;for(int i = 1; i <= 5; i++)for(int j = 1; j <= 5; j++)sum = sum * 3 + map[i][j];a2[++a2_cnt] = (Node){ sum, 7 - step };if(!step)return;x > 1 && y > 2 ? swap(map[x][y], map[x - 1][y - 2]), dfs2(x - 1, y - 2, step - 1), swap(map[x][y], map[x - 1][y - 2]), 0 : 0;x > 2 && y > 1 ? swap(map[x][y], map[x - 2][y - 1]), dfs2(x - 2, y - 1, step - 1), swap(map[x][y], map[x - 2][y - 1]), 0 : 0;x > 1 && y < 4 ? swap(map[x][y], map[x - 1][y + 2]), dfs2(x - 1, y + 2, step - 1), swap(map[x][y], map[x - 1][y + 2]), 0 : 0;x > 2 && y < 5 ? swap(map[x][y], map[x - 2][y + 1]), dfs2(x - 2, y + 1, step - 1), swap(map[x][y], map[x - 2][y + 1]), 0 : 0;x < 5 && y > 2 ? swap(map[x][y], map[x + 1][y - 2]), dfs2(x + 1, y - 2, step - 1), swap(map[x][y], map[x + 1][y - 2]), 0 : 0;x < 4 && y > 1 ? swap(map[x][y], map[x + 2][y - 1]), dfs2(x + 2, y - 1, step - 1), swap(map[x][y], map[x + 2][y - 1]), 0 : 0;x < 5 && y < 4 ? swap(map[x][y], map[x + 1][y + 2]), dfs2(x + 1, y + 2, step - 1), swap(map[x][y], map[x + 1][y + 2]), 0 : 0;x < 4 && y < 5 ? swap(map[x][y], map[x + 2][y + 1]), dfs2(x + 2, y + 1, step - 1), swap(map[x][y], map[x + 2][y + 1]), 0 : 0;
}
int binary_search(ll key) {int l = 1, r = a2_cnt, ans = -1;while(l <= r) {int mid = l + r >> 1;if(a2[mid].val >= key)ans = mid, r = mid - 1;elsel = mid + 1;}return ans;
}
int main() {for(int i = 1; i <= 5; i++)for(int j = 1; j <= 5; j++) {if(i ^ j)map[i][j] = i < j;if(!(i ^ j))map[i][j] = i == 3 ? 2 : i < 3;}a2_cnt = 0;dfs2(3, 3, 7);sort(a2 + 1, a2 + a2_cnt + 1);int t;scanf("%d", &t);while(t--) {int x, y;for(int i = 1; i <= 5; i++) {scanf("%s", s + 1);for(int j = 1; j <= 5; j++) {map[i][j] = s[j] == '*' ? 2 : s[j] - 48;if(map[i][j] == 2)x = i, y = j;}}a1_cnt = 0;dfs1(x, y, 8);int ans = 16;for(int i = 1; i <= a1_cnt; i++) {int l = binary_search(a1[i].val);if(a2[l].val == a1[i].val && a1[i].step + a2[l].step < ans)ans = a1[i].step + a2[l].step;}printf("%d\n", ans == 16 ? -1 : ans);}return 0;
}

骑士精神(双向深搜+meet in the middle)相关推荐

  1. 【深搜】骑士游历(二)

    骑士游历(二) 问题描述:设有一个n×n的棋盘(n≤10),在棋盘上的任意一点A(x,y)有一中国象棋<马>,<马>走的规则同前,但取消<马>只能向右走的条件.试找 ...

  2. 【深搜】骑士游历(ssl 1277)

    骑士游历 Description 如下图所示有m*n(n,m<=15)一个棋盘,在棋盘左下角的A(1,1)点,有一个中国象棋〈马〉,并约定马走的规则: ①走日字:②只能向右走. Sample I ...

  3. poj—2488骑士的旅程(深搜)

    题目: 骑士厌倦了一次又一次地看到相同的黑白方块,并决定 环游世界.每当骑士移动时,它都是一个方向上的两个正方形和一个垂直于此方向的正方形.骑士的世界就是他所生活的棋盘.我们的骑士住在一个棋盘上,这个 ...

  4. bzoj1085: [SCOI2005]骑士精神(a*)

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2555  Solved: 1472 [Submit][St ...

  5. [luogu 2324][SCOI 2005] 骑士精神 (A*算法)

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

  6. BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2838  Solved: 1663 [Submit][St ...

  7. 埃及分数The Rotation Game骑士精神——IDA*

    IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题. 估价函数设计思路:观察一步最多能向答案靠近多少. 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系 ...

  8. bzoj1085骑士精神(搜索)

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1893  Solved: 1051 Description ...

  9. 算法复习——迭代加深搜索(骑士精神bzoj1085)

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

最新文章

  1. 03基于python玩转人工智能最火框架之TensorFlow介绍
  2. centos7中nfs文件系统的使用
  3. 2021年斯坦福AI指数报告重磅出炉!中国AI期刊影响力首超美国,视频处理是新风口...
  4. 解决python2.x文件读写编码问题
  5. Magento 头部的演示信息去除
  6. Unable to generate a temporary class (result=1)解决方法
  7. 《程序员面试金典》最大和子矩阵
  8. ibatis mysql sqlmapconfig_iBATIS sqlMapConfig配置详解
  9. 三、mongodb数据库系列——mongodb和python交互 总结
  10. 【FZU2178】礼物分配
  11. 郑州没有互联网 | 畅言
  12. C语言章节作业第五次,C语言第五次上机作业参考答案
  13. 主成分分析(PCA)实现代码
  14. 澳洲留学生面经,Java后端,阿里、头条、百度、华为、微策略
  15. chart.js使用学习
  16. Flutter shared_preferences简单使用
  17. 曾国藩家训:三个地方看一个家庭的兴败
  18. 联想Y470 非虚拟机安装苹果Mac OS X Mavericks 10.9.1教程详解(文字+图片),通俗易懂亲自动手——序列一之综述简介,硬盘分区
  19. 用python完成一个数独小游戏
  20. java 虚拟机 xms_JVM虚拟机选项:Xms Xmx PermSize MaxPermSize区别(转)

热门文章

  1. 关于SEO(搜索引擎优化)的个人掌握知识分享
  2. 红米note4x Android7,红米Note4X能升级安卓7.0吗?红米Note4X如何升级Android7.0?
  3. mysql 10045错误
  4. HEALER: Relation Learning Guided Kernel Fuzzing学习笔记
  5. matlab-信号与系统
  6. 用户管理系统功能测试报告
  7. 手提电脑安装双屏后没有声音输出
  8. Manifest Permissions
  9. 与一位转行做滴滴司机的前程序员对话引发的思考
  10. C语言基础——运算符(定义变量、转义字符、输入输出语句、运算符、32个关键字)