试题 算法训练 跳马

试题 算法训练 跳马

问题描述
  一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
输入格式
  一行四个数字a,b,c,d。
输出格式
  如果跳不到,输出-1;否则输出最少跳到的步数。
样例输入
1 1 2 3
样例输出
1
嗯…蓝桥上的一个题,一开始用的dfs后来老师说bfs的复杂度啥的好一些,又改进了一下
dfs版本:

#include <iostream>
using namespace std;
//求从(a,b)到(c,d)的最少步数,step为当前步数,min_step为已求得的最小步数
int a, b;//起点
int c, d;//终点
int min_step = -1;//已求得的最小步数
int board[9][9] = {0};//棋盘
//尝试第step步走到(c,d)
void try_step(int i, int j, int step) 
{
   if(min_step!=-1&&step>min_step)
      return;
   else if(i==c&&j==d)//到达目的地
   {
      min_step = step;//发现更少步数的解
      return;//起码这一层递归是停了
   }
   else if(i>=1&&i<=8&&j>=1&&j<=8&&board[i][j]==0)
   {
      board[i][j] = 1;
      try_step(i - 2, j - 1, step + 1);
      try_step(i - 2, j + 1, step + 1);
      try_step(i - 1, j - 2, step + 1);
      try_step(i - 1, j + 2, step + 1);
      try_step(i + 1, j - 2, step + 1);
      try_step(i + 1, j + 2, step + 1);
      try_step(i + 2, j - 1, step + 1);
      try_step(i + 2, j + 1, step + 1);
      //在递归的出口回溯
      board[i][j] = 0;
   }
}
int main()
{
   cin >> a >> b >> c >> d;
   try_step(a, b, 0);
   if(min_step==-1)
      cout << -1 << endl;
   else
      cout << min_step << endl;
   return 0;
}
/*是就比如说走到了某一个顶点记录下用的步数,
 然后如果在别的递归路线里也走到了这个顶点,但是用的步数比它多,
 那么这个用的步数多的递归路线不可能是正确答案,再递归下去也没用了,
 所以直接停止此时这个递归路线,然后在没有递归到底的情况下直接回溯,也就是剪枝,
 然后再尝试别的路线。但是有可能还有其他到这个点的递归路线比当前用的步数还少,
 所以记录下step之后还要擦除访问标志,以便再找到这个点更短的路线。
 也就是说,擦除访问标志就跟悔棋差不多,一看走这里用的步数肯定不是最少,
 然后结束递归把访问标记擦除了再走别处试试。下次走这里发现用的步数比上次少,
 就不回溯,继续走下去试试。*/

bfs版本

#include<iostream>
#include<queue>
using namespace std;
bool vis[10][10]={0};
struct node
{
   int x, y;
   int step;
   node(int x, int y, int step) : x(x), y(y), step(step) {} // 构造函数
};
int dx[8] = {1, 1, -2, -2, 2, 2, -1, -1};
int dy[8] = {2, -2, 1, -1, 1, -1, 2, -2};
queue<node> q;
int bst_search(int a, int b, int c,int d) // BST 作为动态查找(搜索)算法
{
   if (a == c && b == d)
      return 0;
   q.push(node(a,b,0));
   vis[a][b] = true;
   while (!q.empty())
   {
      node t = q.front();
      q.pop();
      for (int i = 0; i < 8; i++)
      {
         int x = t.x + dx[i];
         int y = t.y + dy[i];
         if (x == c && y == d)
         {
            return t.step + 1;
         }
         else if (x >= 1 && x <= 8 && y >= 1 && y <= 8 && !vis[x][y])
         { //在棋盘上但是没有访问
            q.push(node(x,y,t.step+1));
            vis[x][y] = true;
         }
      }
      }
      return -1; //如果跳不到,就返回-1;
   } 
int main()
{
   int a, b, c, d;
   cin >> a >> b >> c >> d;
   cout << bst_search(a, b, c, d);
   return 0;
}

下边是直接入队不用node结构体的一种策略
在这里插入图片描述
在这里插入图片描述

运 用 贪 心 算 法 ,vc++ 语 言 编 写 , 可 单 步 输 出 结 果 【问题描述】 跳马问题也称骑士遍历、马踏棋盘问题:在8*8方格的棋盘上,从任意指定的方格出发,为象棋中的马寻找一条走遍棋盘每一格并且只经过一次的一条路径。 考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。试设计一个算法找出这样一条马的周游路线。 在一个8×8的方格棋盘中,按照国际象棋中马的行走规则从棋盘上的某一方格出发,开始在棋盘上周游,如果能不重复地走遍棋盘上的每一个方格, 这样的一条周游路线在数学上被称为国际象棋盘上马的哈密尔顿链。请你设计一个程序,从键盘输入一个起始方格的坐标,由计算机自动寻找并打印 【算法描述】 本题有较多方法求解,在此仅对回溯法进行分析。 一只马在棋盘的某一点,它可以朝8个方向前进,方向向量分别是:(2,1)、(2,-1)、(1,2)、(1,-2)、(-2,1)、(-2,-1)、(-1,2)、(-1,-2)。从中任选择一个方向前进,到达新的位置。在从新的位置选择一个方向前进,继续,直到无法前进为止。无法前进可能有如下原因:下一位置超出边界、下一位置已经被访问过。当马已经无法前进时,就回退到上一位置,从新选择一个新的方向前进;如果还是无法前进,就再回退到上一位置……
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值