2243:Knight Moves

文章目录

  • 题目描述
  • 思路
    • 1. DFS
    • 2. BFS
    • 3. 动态规划
  • 解题方法
    • 1. DFS
    • 2. BFS
    • 3. 动态规划


题目描述

题目链接

在这里插入图片描述
翻译如下:

注:骑士移动是和象棋里的马一样走的是日字型
你的一个朋友正在研究旅行骑士问题 (TKP),你要找到最短的骑士步数封闭之旅,该游轮在棋盘上只访问一次给定的 n 个方格的每个方格。他认为问题中最困难的部分是确定两个给定方格之间的最小骑士移动次数,一旦你完成了这个任务,找到巡回赛就很容易了。
当然,您知道反之亦然。所以你让他写一个程序来解决“困难”的部分。

你的工作是编写一个程序,将两个方格 a 和 b 作为输入,然后确定从 a 到 b 的最短路线上的骑士移动次数。
输入
输入将包含一个或多个测试用例。每个测试用例由一行组成,其中包含两个方块,由一个空格分隔。正方形是由代表列的字母 (a-h) 和代表棋盘上行的数字 (1-8) 组成的字符串。
输出
对于每个测试用例,打印一行,上面写着“从 xx 到 yy 需要 n 个骑士动作”。

用例:
e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6

输出结果:
To get from e2 to e4 takes 2 knight moves.
To get from a1 to b2 takes 4 knight moves.
To get from b2 to c3 takes 2 knight moves.
To get from a1 to h8 takes 6 knight moves.
To get from a1 to h7 takes 5 knight moves.
To get from h8 to a1 takes 6 knight moves.
To get from b1 to c3 takes 1 knight moves.
To get from f6 to f6 takes 0 knight moves.


思路

这道题要求的就是一个坐标到另一个坐标的最短路径。
路径的求法可以是递归求解(DFS/BFS),也可以是图论求解(Floyd/Dijkstra)。下面我用DFS、BFS、动态规划分别求解这道题。

1. DFS

DFS算法又称深度搜索法,总而言之还是递归三部曲:返回值及传入参数/递归条件/终止条件

  1. 传入参数及返回值
    传入起始坐标,不需要返回值,采用引用方法即可获得结果,用step[i][j]存从起始位置到i行j列的最短距离
	void dfs(int x1,int y1,int result,vector<vector<int> > &step){}
  1. 递归条件
    向四周递归的下一个坐标不超过最大范围,且为了找到最小距离,也要判断当前值是不是比已经存入的值大,如果比存入值还小就更新最短距离,然后接着向下递归
	//判断当前结点坐标是否满足条件 if(x1<0||x1>7||y1<0||y1>7||step[x1][y1]<=result)return ; //更新步数 step[x1][y1]=result;//向下递归 for(int i=0;i<8;i++){dfs(x1+row[i],y1+col[i],result+1,step); 	}
  1. 终止条件
    不满足条件时则终止当前循环

2. BFS

BFS算法又称广度搜索法,是从一个点一层一层向外扩散直至覆盖整个区域,需要用一个队列来暂存遍历的所有结点,方法和递归有所出入,细分应该算是迭代法。

  1. 用一个结构体存每个结点的左边信息以及到达该节点所需的路径长度
struct Node{int x;//横坐标int y;//纵坐标int step;//所需最短路径长度
};
  1. 逐层遍历
    先存入起始结点
void bfs(){queue<Node> que; Node cur,next;cur.x=x1;cur.y=y1;cur.step=0;//当前所在坐标 que.push(cur);  
}
  1. 取出队列头结点,以它为起始节点继续向四周遍历。如果遍历到终止结点则结束广搜;遍历到的结点最短路径在该起始节点的路径长度的基础上加1
while(!que.empty()){cur=que.front();//取出头节点 que.pop();if(cur.x==x2&&cur.y==y2){//已经到达终止位置,结束遍历 cout<<"To get from "<<a<<" to "<<b<<" takes "<<cur.step<<" knight moves."<<endl;return;}for(int i=0;i<8;i++){//继续向四周广搜 next.x=cur.x+row[i];next.y=cur.y+col[i];next.step=cur.step+1;if(next.x<0||next.x>7||next.y<0||next.y>7)continue;//坐标不满足条件 if(next.step!=100){//满足要求的结点存入队列 next.step=cur.step+1;que.push(next);}}
}

3. 动态规划

动态规划五部曲:

  1. dp数组及其下标含义
    dp[i][j]:从初始位置到i行j列的最短距离
  2. 初始化
    起始位置初始化为0,因为是求最短路径,其他位置的值必须保证能让路径被录入,所以初始化为一个较大的值,我初始化为100了
  3. 递推公式
    因为dp[i][j]是可以由日字型一脚的任何一个坐标推导而来
    dp[x][y]=min(dp[x][y],dp[i][j]+1)
  4. 遍历顺序
    我比较蠢,遍历我采用了四种方向,具体为什么我也暂时不太清楚,反正我自己写出来结果是对的,希望有大佬可以为了解答
  5. 打印dp数组

解题方法

1. DFS

#include<iostream>
#include<vector>
#include<string>
using namespace std;
//八个移动方向 
int row[8]={-2,-1,1,2,2,1,-1,-2};
int col[8]={1,2,2,1,-1,-2,-2,-1};void dfs(int x1,int y1,int result,vector<vector<int> > &step){//判断当前结点坐标是否满足条件 if(x1<0||x1>7||y1<0||y1>7||step[x1][y1]<=result)return ; //更新步数 step[x1][y1]=result;//向下递归 for(int i=0;i<8;i++){dfs(x1+row[i],y1+col[i],result+1,step); 	}
}
int main(){ string a,b;while(cin>>a>>b){vector<vector<int> > step(8,vector<int>(8,100));//记录到(i,j)格子的所需步数//end的坐标 int y2=b[0]-'a';int x2=b[1]-'1';	dfs(a[1]-'1',a[0]-'a',0,step);cout<<"To get from "<<a<<" to "<<b<<" takes "<<step[x2][y2]<<" knight moves."<<endl;}
} 

2. BFS

#include<iostream>
#include<vector>
#include<string>
#include<queue> 
using namespace std;
int row[8]={-2,-1,1,2,2,1,-1,-2};
int col[8]={1,2,2,1,-1,-2,-2,-1};
struct Node{int x;//横坐标int y;//纵坐标int step;//所需最短路径长度
};
int x1,y1;//起始坐标 
int x2,y2;//终止坐标 
string a,b;void bfs(){queue<Node> que; Node cur,next;cur.x=x1;cur.y=y1;cur.step=0;//当前所在坐标 que.push(cur);  while(!que.empty()){cur=que.front();//取出头节点 que.pop();if(cur.x==x2&&cur.y==y2){//已经到达终止位置,结束遍历 cout<<"To get from "<<a<<" to "<<b<<" takes "<<cur.step<<" knight moves."<<endl;return;}for(int i=0;i<8;i++){//继续向四周广搜 next.x=cur.x+row[i];next.y=cur.y+col[i];next.step=cur.step+1;if(next.x<0||next.x>7||next.y<0||next.y>7)continue;//坐标不满足条件 if(next.step!=100){//满足要求的结点存入队列 next.step=cur.step+1;que.push(next);}}}
}
int main(){while(cin>>a>>b){//1为起始结点,2为终止结点 x1=a[1]-'1';y1=a[0]-'a';x2=b[1]-'1';y2=b[0]-'a';bfs();}
}

3. 动态规划

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int row[8]={-2,-1,1,2,2,1,-1,-2};
int col[8]={1,2,2,1,-1,-2,-2,-1};
int stx,sty,edx,edy; 
int main(){string a,b;while(cin>>a>>b){stx=a[1]-'1';sty=a[0]-'a';edx=b[1]-'1';edy=b[0]-'a';int dp[8][8]; for(int i=0;i<8;i++){for(int j=0;j<8;j++){dp[i][j]=100;}} dp[stx][sty]=0;//起始位置所需步数为0 //从左到右从上到下遍历 for(int i=0;i<8;i++){for(int j=0;j<8;j++){for(int k=0;k<8;k++){int x=i+row[k];int y=j+col[k];if(x<0||x>7||y<0||y>7||dp[i][j]==100)continue;dp[x][y]=min(dp[x][y],dp[i][j]+1);}}}//从右到左从下到上遍历 for(int i=7;i>=0;i--){for(int j=7;j>=0;j--){for(int k=0;k<8;k++){int x=i+row[k];int y=j+col[k];if(x<0||x>7||y<0||y>7||dp[i][j]==100)continue;dp[x][y]=min(dp[x][y],dp[i][j]+1);}}}//从左到右从下到上遍历 for(int i=0;i<8;i++){for(int j=7;j>=0;j--){for(int k=0;k<8;k++){int x=i+row[k];int y=j+col[k];if(x<0||x>7||y<0||y>7||dp[i][j]==100)continue;dp[x][y]=min(dp[x][y],dp[i][j]+1);}}}//从右到左从上到下遍历 for(int i=7;i>=0;i--){for(int j=0;j<8;j++){for(int k=0;k<8;k++){int x=i+row[k];int y=j+col[k];if(x<0||x>7||y<0||y>7||dp[i][j]==100)continue;dp[x][y]=min(dp[x][y],dp[i][j]+1);}}}//输出结果 cout<<"To get from "<<a<<" to "<<b<<" takes "<<dp[edx][edy]<<" knight moves."<<endl;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP与UDP的区别

TCPUDP连接传送数据前要先建立连接无需建立连接直接传送数据服务对象一对一一对多、多对一、多对多可靠性可靠交付&#xff08;保证数据包的无差错、不失序、不丢包、不重复&#xff09;尽最大努力交付&#xff0c;不保证可靠性&#xff08;但我们可以基于UDP协议实现一个可靠传…

一、Zookeeper基本知识

目录 1、ZooKeeper概述 2、ZooKeeper特性 3、ZooKeeper集群角色 ​​​​​​​1、ZooKeeper概述 Zookeeper是一个分布式协调服务的开源框架。主要用来解决分布式集群中应用系统的一致性问题。 ZooKeeper本质上是一个分布式的小文件存储系统。提供基于类似于文件系统的目录…

web前端之JavaScrip的笔试题

MENU Promise笔试题-02prototype和__proto__的笔试题JavaScript引用类型值值操和运算符优先级比较--笔试原型与原型链--笔试-05作用域-笔试事件队列-笔试题JavaScript之变量提升-笔试题JavaScript之原型链--笔试题 Promise笔试题-02 console.log(1); // 宏仁务 2 setTimeout(_…

[蓝桥杯 2020 省 AB1] 解码

做题前思路&#xff1a; 1.因为是多组输入&#xff0c;又包含字符于是我们可以先定义一个char类型数组arr 2.定义数组的长度&#xff1a;题目说简写&#xff08;字母加数字&#xff09;长度不超过100&#xff0c;但原来的长度可能超过100&#xff0c;加上小明不会将连续超过9…

CSS 滚动捕获 scroll-margin

CSS滚动捕获 scroll-margin 非滚动捕获容器语法兼容性 CSS滚动捕获 scroll-margin 设置元素的滚动外边距 非滚动捕获容器 之前在 scroll-padding 中说过如何用 scroll-padding 避免锚点定位时元素贴着容器边缘的问题, 现在我们尝试用 scroll-margin 解决 <body><ma…

如何使用Java进行人工智能开发?

Java作为一门面向对象的编程语言&#xff0c;在人工智能领域也发挥着重要作用。Java可以借助常见的机器学习库&#xff0c;例如TensorFlow和Keras等&#xff0c;进行机器学习和深度学习的开发。下面是使用Java进行人工智能开发的一些步骤和工具。 准备工作 在使用Java进行人工智…

【C/C++指针】指针*与引用的区别

指针变量的值是所指对象的地址&#xff08;准确说是首地址&#xff0c;其类型定义其所指对象的字节长度&#xff09;引用变量的值是所引用对象本身的值 1 初始化 指针变量 可不初始化 且 可以更换指向对象 int *p;//此时是个野指针&#xff0c;该指针变量的值是任意值&#x…

Kubernetes技术与架构-策略

Kubernetes集群提供系统支持的策略&#xff0c;也提供开放接口给第三方定义的策略&#xff0c;这些策略用于可定义的配置文件或者Kubernetes集群的运行时环境&#xff0c;其中包括进程ID数量的申请与限制策略&#xff0c;服务器节点Node内的进程ID的数量限制策略&#xff0c;Po…

RocketMQ阅读源码前的准备

本文将讲解如何在IDEA中导入 RocketMQ 源码&#xff0c;并运行 Broker 和 NameServer&#xff0c;编写一个消息发送与消息消费的示例。 一. 源码导入及调试 1.1 导入源码 RocketMQ 原先是阿里巴巴集团内部的消息中间件&#xff0c;于2016年提交至Apache基金会孵化&#xff0…

代码随想录算法训练营第三十四天|62.不同路径,63. 不同路径 II

62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#…

oj赛氪练习题

数组调整 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int k scanner.nextInt();int[] arr new int[n];for (int i 0; i < n; i) {arr[i] scanner.nextIn…

python+Qt5+sqllite 个性化单词记忆软件设计

问题描述&#xff1a; 设计一款背诵英语单词的软件。用户可以根据自己的需求导入需背诵的词库&#xff0c;并可以编辑自己的词库。背单词时有两种模式供选择&#xff1a;系统可以给出中文提示&#xff0c;用户输入对应的单词&#xff0c;也可输出单词让用户输入中文意思。系统判…

react-native实践日记--6.ReactNative 项目版本升级,0.61到0.72升级的问题记录(二)

接上一篇&#xff0c;ReactNative项目升级&#xff0c;0.61到0.72的升级问题。 在升级过程中&#xff0c;发现react-native-scrollable-tab-view这个tab插件&#xff0c;这是一个tab导航栏插件&#xff0c;可以实现切换页面、页面滚动、下拉刷新、上拉加载更多等&#xff0c;功…

二叉树的前,中,后序遍历(递归法和迭代法) Python

二叉树的前序遍历 递归法&#xff1a; # 定义二叉树节点的类 # class TreeNode: # def __init__(self, x): # self.val x # self.left None # self.right Noneclass Solution:def preorderTraversal(self, root: Optional[TreeNode]) -> List[…

【pytest】执行环境切换的两种解决方案

一、痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&#xff0c;比如多套测试环境、预上线环境、UAT环境、线上环境等等&#xff0c;并且在DevOps理念中&#xff0c;往往自动化都会与Jenkins进行CI/CD&#xff0c;不论是定时执行策略…

SQL解惑 - 谜题2

文章目录 一、谜题描述二、分析三、答案四、总结 一、谜题描述 创建一个记录雇员缺勤率的数据库。使用的表结构如下&#xff1a;Absenteeism 主键&#xff1a;PRIMARY KEY (emp_id, absent_date) 字段名字段类型字段中文名字段描述emp_idINTERGER雇员id-absent_dateSTRING缺勤…

【数据中台】开源项目(5)-Amoro

介绍 Amoro is a Lakehouse management system built on open data lake formats. Working with compute engines including Flink, Spark, and Trino, Amoro brings pluggable and self-managed features for Lakehouse to provide out-of-the-box data warehouse experience,…

SQL优化的面试题

1. **针对慢查询进行性能优化**&#xff1a; - 使用数据库提供的工具&#xff08;如MySQL的EXPLAIN语句&#xff09;分析查询计划&#xff0c;找出潜在的性能问题。 - 优化查询语句的结构&#xff0c;确保索引被充分利用。 - 对于大表&#xff0c;考虑分页或缓存部分结…

6-2 统计大于等于平均分人数

函数 fun 的功能是&#xff1a;从m个学生的成绩中统计出高于和等于平均分的学生人数&#xff0c; 此人数由函数值返回。平均分通过形参传回&#xff0c;输入学生成绩时&#xff0c; 用-1结束输入&#xff0c;由程序自动统计学生人数。 函数接口定义&#xff1a; int fun ( fl…

【无标题】AttributeError: module ‘gradio‘ has no attribute ‘outputs‘

问题描述 AttributeError: module gradio has no attribute outputs 不知道作者用的是哪个gradio版本&#xff0c;最新的版本报错AttributeError: module gradio has no attribute outputs &#xff0c; 换一个老一点的版本会报错AttributeError: module gradio has no attribu…