2243:Knight Moves

news2024/12/23 19:29:16

文章目录

  • 题目描述
  • 思路
    • 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.coloradmin.cn/o/1277739.html

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

相关文章

java学习part28线程安全Lock锁方式

138-多线程-线程安全的懒汉式_死锁_ReentrantLock的使用_哔哩哔哩_bilibili 1.lock类变量 2.使用方法 和以前的加锁一样&#xff0c;同步代码前加锁&#xff0c;代码后解锁&#xff0c;就表示锁住了这一块代码。 lock是上面声明的静态常量 3.同步和加锁对比

通义千问 模型学习 和 SDK试用

通义千问-14B-Chat-Int4 模型库 (modelscope.cn) **通义千问-14B&#xff08;Qwen-14B&#xff09;**是阿里云研发的通义千问大模型系列的140亿参数规模的模型。Qwen-14B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样&#xff0…

2023年第十二届数学建模国际赛小美赛C题雪崩防范求解分析

2023年第十二届数学建模国际赛小美赛 C题 雪崩防范 原题再现&#xff1a; 雪崩是极其危险的现象。现在&#xff0c;我们对雪崩是如何形成的已经有了很好的理解&#xff0c;但是我们还不能详细地预测雪崩发生的原因、时间和地点。村庄和道路可以通过各种方式防止雪崩。避免在脆…

python datetime 获取特定一天的后一天或者后几天

这里写自定义目录标题 1 获取特定天的时间对象 具体时间格式参考&#xff1a;Python time strptime()和strftime()-CSDN博客 import datetimetimer datetime.datetime.strptime(date, "%Y-%m-%d")2 获取下一天或者【下x天】的数据并进行格式转换 # 下一天数据 ne…

编译原理:设计与实现一个简单词法分析器

设计与实现一个简单词法分析。具体内容是产生一个二元式文本文件&#xff0c;扩展名为dyd&#xff0c;可将Java或C程序(测试程序)分解成为一个一个的单词及类型。 &#xff08;选做&#xff1a;并查“单词符号与种别对照表”得出其种别&#xff0c;用一数字表示。&#xff09;…

Redis数据结构之压缩列表

压缩列表是Redis为节约内存而开发的&#xff0c;是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点&#xff0c;每个节点可以保存一个字节数组或者整数值。 压缩列表构成 zlbytes: 记录整个压缩列表占用的内存字节数&#xff0c;对压缩列…

【每日一题】1094. 拼车-2023.12.2

题目&#xff1a; 1094. 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数组 trips , trip[i] [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi…

Android 缩减、混淆处理和优化应用

为了尽可能减小应用的大小&#xff0c;您应在发布 build 中启用缩减功能来移除不使用的代码和资源。启用缩减功能后&#xff0c;您还会受益于两项功能&#xff0c;一项是混淆处理功能&#xff0c;该功能会缩短应用的类和成员的名称&#xff1b;另一项是优化功能&#xff0c;该功…

eclipse中设置自动补齐代码

eclipse中设置自动补齐代码 01 在window里找到preference 02 在preference里搜索content assist 03 在Java的content assist设置 设置为.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 04 apply and close即可

PyLMKit(3):基于角色扮演的应用案例

角色扮演应用案例RolePlay 0.项目信息 日期&#xff1a; 2023-12-2作者&#xff1a;小知课题: 通过设置角色模板并结合在线搜索、记忆和知识库功能&#xff0c;实现典型的对话应用功能。这个功能是大模型应用的基础功能&#xff0c;在后续其它RAG等功能中都会用到这个功能。功…

Linux基础项目开发1:量产工具——UI系统(五)

前言&#xff1a; 前面我们已经把显示系统、输入系统、文字系统搭建好了&#xff0c;现在我们就要给它实现按钮操作了&#xff0c;也就是搭建UI系统&#xff0c;下面让我们一起实现UI系统的搭建吧 目录 一、按钮数据结构抽象 ui.h 二、按键编程 1.button.c 2.disp_manager…

赤峰学院师资培养管理系统的设计与实现

摘 要 随着我国国民经济建设的蓬勃发展和信息技术的越发成熟&#xff0c;各个行业都在积极使用现代化的管理工具&#xff0c;不断改善企业的服务质量&#xff0c;提高工作效率。对师资培养进行现代化的管理&#xff0c;提高工作效率是师资培养管理系统的一大优点。本文是一篇关…

Aspice(Automotive Software Process Improvement and Capability Determination)

Aspice&#xff08;Automotive Software Process Improvement and Capability Determination&#xff09; 1. 引言&#xff1a;ASPICE概述 定义 ASPICE简介&#xff1a;ASPICE&#xff08;Automotive Software Process Improvement and Capability Determination&#xff09;…

Qt Creator 11.0.3同时使用Qt6.5和Qt5.14.2

Qt Creator 11.0.3同时使用Qt6.5和Qt5.14.2 概要方法1.打开Qt Creator中的Kit&#xff0c;这里我直接附上几张截图&#xff0c;不同的版本打开位置可能有所不同&#xff0c;总之最终目的是要打开构建套件&#xff08;Kit&#xff09;2.可以看到构建套件里面有包含了“构建套件K…

栈顺序存储的实现(详解)

栈是一种数据结构&#xff0c;它具有后进先出&#xff08;LIFO&#xff09;的特性。栈可以用来存储一组元素&#xff0c;并且只能在栈顶进行插入和删除操作。栈的基本概念包括&#xff1a; 1. 入栈&#xff08;push&#xff09;&#xff1a;将元素添加到栈顶的操作。 2. 出栈&…

【halcon】C# halcon 内存暴增

1 读取图片需要及时手动释放 一个6M的图片通过halcon进行加载&#xff0c;大约会消耗200M的内存&#xff0c;如果等待GC回收&#xff0c;而你又在不停的读取图片&#xff0c;你的内存占用&#xff0c;将在短时间内飙升。 2 halcon控件显示图片需要清空。 /// <summary>…

Motion 5 for Mac,释放创意,打造精彩视频特效!

Motion 5 for Mac是一款强大的视频后期特效处理软件&#xff0c;为Mac用户提供了无限的创意可能性。无论你是专业的影视制作人&#xff0c;还是想为个人视频添加独特特效的爱好者&#xff0c;Motion 5都能满足你的需求&#xff0c;让你的视频脱颖而出。 Motion 5提供了丰富多样…

数据链路层之VLAN基本概念和基本原理

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

线程与多线程编程

1. 线程 1.1 概念 线程又可以称为轻量级进程 &#xff0c;在进程的基础上做出了改进。 一个进程在刚刚启动时&#xff0c;做的第一件事就是申请内存和资源&#xff0c;进程需要把依赖的代码和数据&#xff0c;从磁盘加载到内存中这件事是比较耗费时间的&#xff0c;有的业务…

国产AI边缘计算盒子,双核心A55丨2.5Tops算力

边缘计算盒子 双核心A55丨2.5Tops算力 ● 2.5TopsINT8算力&#xff0c;支持INT8/INT4/FP16多精度混合量化。 ● 4路以上1080p30fps视频编解码&#xff0c;IVE模块独立提供图像基础算子加速。 ● 支持Caffe、ONNX/PyTorch深度学习框架&#xff0c;提供resnet50、yolov5等AI算…