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.rhkb.cn/news/209848.html

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

相关文章

Android 断点调试

Android 调试 https://developer.android.google.cn/studio/debug?hlzh-cn 调试自己写的代码&#xff08;不在Android源码&#xff09; 点击 Attach debugger to Android process 图标 需要在添加断点界面手动输入函数名 但也可以不手动&#xff0c;有个技巧可以new 空proje…

个人博客搭建保姆级教程-HTML页面编写篇

选择模板 首先我们要选一个好的模板&#xff0c;然后对模板进行剪裁。我的模板是在站长之家进行下载的 素材下载-分享综合设计素材免费下载的平台-站长素材 我选的模板的具体地址是 个人博客资讯网页模板 这里需要我们学习一下在前边一篇文章里提到的HTML、JavaScript、CSS…

C++ :运算符重载

运算符重载&#xff1a; 运算符重载概念&#xff1a;对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型 运算符的重载实际是一种特殊的函数重载&#xff0c;必须定义一个函数&#xff0c;并告诉C编译器&#xff0c;当遇到该重载的运算符…

华为拆分零部件业务,长安入股,赛力斯接洽中

作者 |德新 编辑 |王博 11月26日&#xff0c;长安汽车官宣与华为在智能汽车零部件业务上的投资与合作&#xff1a; 华为拟成立一家新的公司&#xff0c;并将其在智能汽车解决方案业务上的核心技术和资源注入新公司&#xff0c;长安汽车及关联方有意投资该新公司。 参照目前长…

浮点数二分例题:数的三次方根-Java版

//浮点数二分,正常写就行,不用考虑死循环问题import java.util.Scanner;public class Main{public static void main(String[] args) {Scanner sc new Scanner(System.in);Double n sc.nextDouble();double l -100,r 100;//数据范围是100000,开了三次方后不会超过100//小知…

【Altium designer 20】

Altium designer 20 1. Altium designer 201.1 原理图库1.1.1 上划岗 在字母前面加\在加字母1.1.2 自定义快捷键1.1.3 对齐1.1.4 在原有的电路图中使用封装1.1.5 利用excel创建IC类元件库1.1.6 现有原理图库分类以及调用1.1.7 现有原理图库中自动生成原理图库 1.2 绘制原理图1.…

质量小议35 -- SQL注入

已经记不得上次用到SQL注入是什么时候了&#xff0c;一些概念和操作已经模糊。 最近与人聊起SQL注入&#xff0c;重新翻阅&#xff0c;暂记于此。 重点&#xff1a;敏感信息、权限过大、未脱敏的输入/输出、协议、框架、数据包、明文、安全意识 SQL - Structured Query La…

打破卫浴行业冰山!九牧重构高端服务品牌“点线面”新秩序

文 | 螳螂观察 作者 | 余一 说到服务&#xff0c;你首先会想到哪个品牌&#xff1f;海底捞大概率会是其中之一。 一个餐饮品牌&#xff0c;不靠价格、口味出圈&#xff0c;而是凭借服务走向全球市场&#xff0c;古往今来或许也是头一家了&#xff0c;而无微不至的的服务&…

设计模式-结构型模式之桥接设计模式

文章目录 三、桥接模式 三、桥接模式 桥接模式&#xff08;Bridge&#xff09;是用于把抽象化与实现化解耦&#xff0c;使得二者可以独立变化。它通过提供抽象化和实现化之间的桥接结构&#xff0c;来实现二者的解耦。 这种模式涉及到一个作为桥接的接口&#xff0c;使得实体类…

MySQL安装

目录 MySQL简介 MySQL安装 连接MySQL数据库 MySQL简介 MySQL是最流行的关系型数据库管理系统之一&#xff0c;属于Oracle旗下产品。由于其体积小、速度快、总体拥有成本低&#xff0c;尤其是开放源码这一特点&#xff0c;一般中小型和大型网站的开发都选择 MySQL作为网站数据…

JVM:双亲委派(未完结)

类加载 定义 一个java文件从编写代码到最终运行&#xff0c;必须要经历编译和类加载的过程&#xff0c;如下图&#xff08;图源自b站视频up主“跟着Mic学架构”&#xff09;。 编译就是把.java文件变成.class文件。类加载就是把.class文件加载到JVM内存中&#xff0c;得到一…

使用Docker安装部署Swagger Editor并远程访问编辑API文档

文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagger Editor2. Linux安装Cpolar3. 配置Swagger Editor公网地址4. 远程访问Swagger Editor5. 固定Swagger Editor公网地址 Swagger Editor本地接口文档公网远程访问 Swagger Editor是一个用于编写OpenAPI规范的开源编…

UE5 - 虚幻引擎各模块流程图

来自虚幻官方的一些资料&#xff0c;分享一下&#xff1b; 一些模块的流程图&#xff0c;比如动画模块&#xff1a; 或角色相关流程&#xff1a; 由于图片比较大&#xff0c;上传到了网络&#xff0c;可自取&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1BQ2KiuP08c…

GitHub项目推荐-Deoldify

有小伙伴推荐了一个老照片上色的GitHub项目&#xff0c;看了简介&#xff0c;还不错&#xff0c;推荐给大家。 项目地址 GitHub - SpenserCai/sd-webui-deoldify: DeOldify for Stable Diffusion WebUI&#xff1a;This is an extension for StableDiffusions AUTOMATIC1111 w…

Allegro无法模块复用的解决办法

Allegro无法模块复用的解决办法 在用Allegro做PCB设计的时候,模块复用是使用的比较频繁的功能,对于有相同模块的单板,可以节省大量的时间。 模块复用的功能不细说,具体参考以前的文章。 有时会遇到模块复用的时候出现如下报错 无法匹配,有时如果因为Device而无法复用,就…

SWD和JTAG

1、调试接口概念 1&#xff09;SWD&#xff1a;Serial Wire Debug&#xff0c;代表串行线调试&#xff0c;是ARM设计的协议&#xff0c;用于对其微控制器进行编程和调试。 SWD 引脚&#xff1a; SWDIO–串行数据线&#xff0c;用于数据的读出和写入SWDCLK–串行时钟线&#…

实现用户登陆

输入用户名和密码&#xff0c;如果输入用户名和密码正确&#xff0c;允许登录 编程过程中采用字符串拉接。 SQL注入&#xff0c;当使用拼接的sql语句. 输入密码时把语句拼接成or&#xff0c;or后面跟上一个条件正确的式子。 Java 防止sql注入&#xff0c;预编译手段&#xff…

使用Pytorch从零开始实现CLIP

生成式建模知识回顾: [1] 生成式建模概述 [2] Transformer I&#xff0c;Transformer II [3] 变分自编码器 [4] 生成对抗网络&#xff0c;高级生成对抗网络 I&#xff0c;高级生成对抗网络 II [5] 自回归模型 [6] 归一化流模型 [7] 基于能量的模型 [8] 扩散模型 I, 扩散模型 II…

Python按要求从多个txt文本中提取指定数据

基本想法 遍历文件夹并从中找到文件名称符合我们需求的多个.txt格式文本文件&#xff0c;并从每一个文本文件中&#xff0c;找到我们需要的指定数据&#xff0c;最后得到所有文本文件中我们需要的数据的集合 举例 如现有名为file一个文件夹&#xff0c;里面含有大量的.txt格…

浅谈用户体验测试的主要功能

用户体验(User Experience&#xff0c;简称UX)在现代软件和产品开发中变得愈发重要。为了确保产品能够满足用户期望&#xff0c;提高用户满意度&#xff0c;用户体验测试成为不可或缺的环节。本文将详细探讨用户体验测试的主要功能&#xff0c;以及它在产品开发过程中的重要性。…