马的管辖

结果填空:马的管辖 - 题库 - 计蒜客 (jisuanke.com)

在中国象棋中,马是走日字的。一个马的管辖范围指的是当前位置以及一步之内能走到的位置,下图的绿色旗子表示马能走到的位置。

如果一匹马的某个方向被蹩马脚,它就不能往这个方向跳了,如下图所示,海星的位置存在旗子,马就不能往上跳到那两个位置了:

那么问题来了,在一个 n\times mn×m 的棋盘内,如何用最少的马管辖住所有 n\times mn×m 个格子。比如 n=m=3n=m=3 时,最少要用 55 只马才能管辖所有棋盘,一种可能的方案如下: 

当 n=m=5n=m=5 时,请你求出用最少马管辖的 方案个数

思路:就是全排了,暴力法可以弄出来,不过查了一下没有深搜,所以 写一下深搜思路

用二维数组比较方便,先初始后一个二维数组m*m

static int map[][] = new int[m][m];
static int vmap[][] = new int[m][m];

vmap[][]是虚拟地图,用来记录map[][]对应是否被标记过

接下来是dfs代码:

 static void dfs(int step) {if (step == m * m) {if (targetloop()) {for (int i = 0; i < m; i++) {for (int j = 0; j < m; j++) {System.out.print(map[i][j]);}System.out.println();}System.out.println();}return;}for (int j2 = 0; j2 <= 1; j2++) {int x = step / m;int y = step % m;if (vmap[x][y] == 0) {vmap[x][y] = 1;map[x][y] = j2;dfs(step + 1);vmap[x][y] = 0;}}}

返回点肯定是step=m*m,这里for循环0和1,0相当于空位,1相当于马位,x坐标等step/m,y坐标等于step%m,这样我们就能跟着step来一层层递归,targetloop()是检测,检测是否填满检测是否最小方案(记得检测是否憋马脚),如果检测通过则输出,下面重点在targetloop。

static boolean targetloop() {boolean sum0 = true;int sum1 = 0;int dir2[][] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };//憋马脚的位置,逆时针存放,对应dir顺序int dir[][] = { { -2, -1 }, { -2, 1 }, { -1, -2 }, { 1, -2 }, { 2, -1 }, { 2, 1 }, { -1, 2 }, { 1, 2 }};//马可以跳的位置,逆时针存放,待会检测憋马脚也是逆时针检测,对应dir2顺序int testmap[][] = new int[m][m];//再来个测试地图,记录每个马位置(标记1)和马可以跳的位置(标记2)for (int i = 0; i < map.length; i++) {for (int j = 0; j < map.length; j++) {if (map[i][j] == 1) {testmap[i][j] = 1;    //真实地图马位赋值给测试地图}}}for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {if (testmap[i][j] == 1) {for (int k = 0; k < dir.length; k++) { //检测8个马可以跳方向int xx = dir[k][0] + i;//当前马跳的坐标xint yy = dir[k][1] + j;//当前马跳的坐标yif (xx >= 0 && xx < m && yy >= 0 && yy < m) { //边界判断//检测马跳位置的马脚是否憋住int xxx = dir2[k / 2][0] + i;///当前检测憋马脚的坐标x,这里的k对应马跳位置的顺序一个方向可以憋两个位置int yyy = dir2[k / 2][1] + j;///当前检测憋马脚的坐标y,这里的k对应马跳位置的顺序一个方向可以憋两个位置if (xxx >= 0 && xxx < m && yyy >= 0 && yyy < m) {if (testmap[xxx][yyy] != 1) {if (testmap[xx][yy]==0) {testmap[xx][yy] = 2; //如果没有憋住也有空位,则为2,标记可以跳}}}}}}}}for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {if (testmap[i][j] == 0) { //检测是否把空位填满sum0 = false;}if (testmap[i][j] == 1) {sum1++;  //计算马的数量}}}if (sum0) {if (min >= sum1) {  //检测马数是否是最小,因为递归是逆推的,所以默认是从最小的开始排列,只要记录最小可以满足方案马的数量,则一直按照最小数量那个来就行min = sum1; //记录最小马位for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {System.err.print(testmap[i][j]);}System.err.println();}System.out.println();loopsum++;//马的满足方案+1return true;}}return false;}

重点在马跳的位置和憋马位置,方向要对应,最后计算是否被马和马对应跳的位置铺满即可(记得检测一下是否为最小马的数量)。

完整代码如下:

public class Main {static int min = Integer.MAX_VALUE;static int m = 5;//可以自行修改  测试m*m地图static int loopsum = 0;static int map[][] = new int[m][m];static int vmap[][] = new int[m][m];public static void main(String[] args){for (int i = 0; i < m; i++) {for (int j = 0; j < m; j++) {map[i][j] = 0;}}dfs(0);System.err.println(loopsum);}static void dfs(int step) {if (step == m * m) {if (targetloop()) {for (int i = 0; i < m; i++) {for (int j = 0; j < m; j++) {System.out.print(map[i][j]);}System.out.println();}System.out.println();}return;}for (int j2 = 0; j2 <= 1; j2++) {int x = step / m;int y = step % m;if (vmap[x][y] == 0) {vmap[x][y] = 1;map[x][y] = j2;dfs(step + 1);vmap[x][y] = 0;}}}static boolean targetloop() {boolean sum0 = true;int sum1 = 0;int dir2[][] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };//憋马脚的位置,逆时针存放,对应dir顺序int dir[][] = { { -2, -1 }, { -2, 1 }, { -1, -2 }, { 1, -2 }, { 2, -1 }, { 2, 1 }, { -1, 2 }, { 1, 2 }};//马可以跳的位置,逆时针存放,待会检测憋马脚也是逆时针检测,对应dir2顺序int testmap[][] = new int[m][m];//再来个测试地图,记录每个马位置(标记1)和马可以跳的位置(标记2)for (int i = 0; i < map.length; i++) {for (int j = 0; j < map.length; j++) {if (map[i][j] == 1) {testmap[i][j] = 1;    //真实地图马位赋值给测试地图}}}for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {if (testmap[i][j] == 1) {for (int k = 0; k < dir.length; k++) { //检测8个马可以跳方向int xx = dir[k][0] + i;//当前马跳的坐标xint yy = dir[k][1] + j;//当前马跳的坐标yif (xx >= 0 && xx < m && yy >= 0 && yy < m) { //边界判断//检测马跳位置的马脚是否憋住int xxx = dir2[k / 2][0] + i;///当前检测憋马脚的坐标x,这里的k对应马跳位置的顺序一个方向可以憋两个位置int yyy = dir2[k / 2][1] + j;///当前检测憋马脚的坐标y,这里的k对应马跳位置的顺序一个方向可以憋两个位置if (xxx >= 0 && xxx < m && yyy >= 0 && yyy < m) {if (testmap[xxx][yyy] != 1) {if (testmap[xx][yy]==0) {testmap[xx][yy] = 2; //如果没有憋住也有空位,则为2,标记可以跳}}}}}}}}for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {if (testmap[i][j] == 0) { //检测是否把空位填满sum0 = false;}if (testmap[i][j] == 1) {sum1++;  //计算马的数量}}}if (sum0) {if (min >= sum1) {  //检测马数是否是最小,因为递归是逆推的,所以默认是从最小的开始排列,只要记录最小可以满足方案马的数量,则一直按照最小数量那个来就行min = sum1; //记录最小马位for (int i = 0; i < testmap.length; i++) {for (int j = 0; j < testmap.length; j++) {System.err.print(testmap[i][j]);}System.err.println();}System.out.println();loopsum++;//马的满足方案+1return true;}}return false;}
}

跑出结果还是需要十几秒,就当练习一下全排, 最后答案:90

马的管辖-----深搜代码相关推荐

  1. 百练_4123 马走日(深搜)

    描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行为整数T ...

  2. 马走日-深搜回溯-超好懂题解

    马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. Input 第一行为整数T ...

  3. nyoj-20-吝啬的国度(深搜)

    吝啬的国度 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 在一个吝啬的国度里有N个城市.这N个城市间仅仅有N-1条路把这个N个城市连接起来.如今,Tom在第S号城市 ...

  4. NYOJ 10 skiing (深搜和动归)

    skiing 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 5 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且 ...

  5. 马走日(深搜 C++)

    马走日 总时间限制: 1000ms 内存限制: 1024kB 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点, ...

  6. dfs算法题目(深搜思想训练)

    迷宫游戏 我们用一个二维的字符数组来表示前面画出的迷宫: 其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地.你需要从S出发走到T,每次只能向上下左右相邻的位置移动,不能走出地图,也不 ...

  7. 深搜和广搜(初学者)

    搜索入门 最近对搜索有了一点浅显的了解,想跟大家分享分享. 说起来我也是初学者,恰巧有些自己的理解,想起来自己开始学习搜索的情况,真是一把鼻子一把泪啊.所以想把我领悟的过程,看到的一些基础的我觉得好的 ...

  8. Go 分布式学习利器(15) -- Go 实现 深搜和广搜

    强化语法,回顾算法. 通过Go语言实现 深度优先搜索 和 广度优先搜索,来查找社交网络中的三度好友关系(三度指的是一个节点到 其相邻节点 到 其相邻节点的节点 ,图递增三层好友关系). 涉及到的Go语 ...

  9. 水管工游戏 (深搜)

    水管工游戏 本题依然是采用搜索,深搜,广搜都可以,本代码采用深搜,此题在搜索时需要增加一些判断条件以及下一步要搜索的位置即可. 代码如下: #include<stdio.h> int a[ ...

最新文章

  1. 最新|全球药企15强(附名单)
  2. 柳传志给年轻人的建议:比起过日子,更要奔日子
  3. SQL Server 2005 cmd工具的使用
  4. csh远程登录服务器,ubuntu远程连接服务器某一个用户(非root用户)出现sh: 1: source: not found...
  5. xml 纯内容标签_Python小课堂XML 解析
  6. MQTT工作笔记0006---CONNECT控制报文3
  7. Javascript:一些基本语法
  8. PowerPoint 蜜蜂跳“8”字舞实例
  9. C语言的输出对齐应用
  10. 微博营销的优劣势。如何利用微博开展营销。
  11. 360 技术岗秋招笔试原题(2022届)
  12. ddr走线教程_DDR3 Fly By走线精讲
  13. echarts:基于上一篇我来给大家讲讲 如果你设置了自动播放但是鼠标放上去不生效 停留时间很短 应该怎么做呢???
  14. 鸡和兔关在一个笼子里,鸡有2只脚,兔有4只脚,螃蟹 ;递归
  15. Springboot359的医院病历管理系统
  16. 互联网公司的中年人都去哪了?
  17. microstation level3 10 elliptical cone solid 、ellipsoid、polyhedron
  18. Windows10+Ubuntu双系统安装[
  19. 年仅22岁的苹果视障工程师正在改变科技世界
  20. 专属于网络安全行业的习惯

热门文章

  1. 【硬核教程】作为一个程序员,怎么做才能母亲在母亲节感到双倍快乐
  2. 官方指定Jmeter配置JVM堆内存方式
  3. windows重启php服务,windows server 下重启 MySQL(服务)
  4. 学生上课睡觉班主任怎么处理_怎样解决学生上课睡觉的问题
  5. pxcook导出html代码,Pxcook标注工具的具体使用方法介绍
  6. 抖音Java后端123面开挂,复习指南
  7. Linux下find与exec的联手干大事
  8. 超融合架构hci之路坦力nutanix之硬件规格及软件配置之一
  9. 用数学方法计算井字棋合法局面数——波利亚定理的简单应用
  10. AnLink打通电脑与手机操作和数据互通的专用工具