2023-08-16:用go语言如何解决进击的骑士算法问题呢?
2023-08-16:用go写算法。一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上,
你的 骑士 驻扎在坐标为 [0, 0] 的方格里。
骑士的走法和中国象棋中的马相似,走 “日” 字:
即先向左(或右)走 1 格,再向上(或下)走 2 格,
或先向左(或右)走 2 格,再向上(或下)走 1 格,
每次移动,他都可以像中国象棋中的马一样,选八个方向中的一个前进。
返回 骑士前去征服坐标为 [x, y] 的部落所需的最小移动次数。
本题确保答案是一定存在的。
输入:x = 2, y = 1。
输出:1。
解释:[0, 0] → [2, 1]。
输入:x = 5, y = 5。
输出:4。
解释:[0, 0] → [2, 1] → [4, 2] → [3, 4] → [5, 5]。
提示:|x| + |y| <= 300。
来自Indeed、谷歌、亚马逊、领英、英伟达。
来自左程云。
答案2023-08-16:
大体步骤如下:
1.初始化一个二叉堆(binary heap)和一个哈希表(hashmap)用于存储已访问的位置。
2.将起始位置 [0, 0] 添加到二叉堆中,并初始化最小移动次数为无穷大。
3.进入循环,直到二叉堆为空:
弹出堆顶位置,获取当前位置的代价、行号和列号。
检查当前位置是否已经访问过,如果是则跳过该位置。
检查当前位置是否达到目标位置,如果是则更新最小移动次数为当前代价,并结束循环。
标记当前位置为已访问。
尝试向八个方向移动,将可行的新位置添加到二叉堆中。
4.返回最小移动次数。
总的时间复杂度:在最坏情况下,需要访问所有格子,每次访问需要将新位置添加到二叉堆中,时间复杂度为O(N log N),其中N是需要访问的格子数量。
总的额外空间复杂度:使用了二叉堆和哈希表来存储已访问的位置,额外空间复杂度为O(N),其中N是需要访问的格子数量。
go完整代码如下:
package main
import (
"fmt"
"math"
"github.com/emirpasic/gods/maps/hashmap"
"github.com/emirpasic/gods/sets/hashset"
"github.com/emirpasic/gods/trees/binaryheap"
)
// minKnightMoves calculates the minimum number of moves required for a knight to reach position (x, y).
func minKnightMoves(x, y int) int {
heap := binaryheap.NewWith(func(a, b interface{}) int {
return int(a.([]int)[0] + a.([]int)[1] - b.([]int)[0] - b.([]int)[1])
})
closed := hashmap.New()
heap.Push([]int{0, distance(0, 0, x, y), 0, 0})
ans := math.MaxInt32
for heap.Size() > 0 {
c, _ := heap.Pop()
cur := c.([]int)
cost := cur[0]
row := cur[2]
col := cur[3]
if isClosed(closed, row, col) {
continue
}
if row == x && col == y {
ans = cost
break
}
close(closed, row, col)
add(cost+1, row+2, col+1, x, y, closed, heap)
add(cost+1, row+1, col+2, x, y, closed, heap)
add(cost+1, row-1, col+2, x, y, closed, heap)
add(cost+1, row-2, col+1, x, y, closed, heap)
add(cost+1, row-2, col-1, x, y, closed, heap)
add(cost+1, row-1, col-2, x, y, closed, heap)
add(cost+1, row+1, col-2, x, y, closed, heap)
add(cost+1, row+2, col-1, x, y, closed, heap)
}
return ans
}
// isClosed checks if the position (r, c) has been visited before.
func isClosed(closed *hashmap.Map, r, c int) bool {
set, found := closed.Get(r)
if !found {
return false
}
return set.(*hashset.Set).Contains(c)
}
// close adds the position (r, c) to the closed set.
func close(closed *hashmap.Map, r, c int) {
set, found := closed.Get(r)
if !found {
set = hashset.New()
closed.Put(r, set)
}
set.(*hashset.Set).Add(c)
}
// add adds the position (r, c) to the heap if it hasn't been visited before.
func add(cost, r, c, x, y int, closed *hashmap.Map, heap *binaryheap.Heap) {
if !isClosed(closed, r, c) {
heap.Push([]int{cost, distance(r, c, x, y), r, c})
}
}
// distance calculates the Manhattan distance divided by 3.
// This is used as the heuristic function for estimating the cost.
func distance(r, c, x, y int) int {
return (int(math.Abs(float64(x-r))) + int(math.Abs(float64(y-c)))) / 3
}
func main() {
x, y := 2, 1
result := minKnightMoves(x, y)
fmt.Println(result)
}

rust完整代码如下:
use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
#[derive(Copy, Clone, Eq, PartialEq)]
struct KnightMove {
cost: i32,
distance: i32,
row: i32,
col: i32,
}
impl Ord for KnightMove {
fn cmp(&self, other: &Self) -> Ordering {
(self.cost + self.distance)
.cmp(&(other.cost + other.distance))
.reverse()
}
}
impl PartialOrd for KnightMove {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
fn min_knight_moves(x: i32, y: i32) -> i32 {
let mut heap = BinaryHeap::new();
let mut closed: HashMap<i32, HashMap<i32, bool>> = HashMap::new();
heap.push(KnightMove {
cost: 0,
distance: distance(0, 0, x, y),
row: 0,
col: 0,
});
let mut ans = i32::MAX;
while let Some(cur) = heap.pop() {
let cost = cur.cost;
let row = cur.row;
let col = cur.col;
if is_popped(&closed, row, col) {
continue;
}
if row == x && col == y {
ans = cost;
break;
}
close(&mut closed, row, col);
add(cost + 1, row + 2, col + 1, x, y, &mut closed, &mut heap);
add(cost + 1, row + 1, col + 2, x, y, &mut closed, &mut heap);
add(cost + 1, row - 1, col + 2, x, y, &mut closed, &mut heap);
add(cost + 1, row - 2, col + 1, x, y, &mut closed, &mut heap);
add(cost + 1, row - 2, col - 1, x, y, &mut closed, &mut heap);
add(cost + 1, row - 1, col - 2, x, y, &mut closed, &mut heap);
add(cost + 1, row + 1, col - 2, x, y, &mut closed, &mut heap);
add(cost + 1, row + 2, col - 1, x, y, &mut closed, &mut heap);
}
ans
}
fn is_popped(closed: &HashMap<i32, HashMap<i32, bool>>, r: i32, c: i32) -> bool {
if let Some(cols) = closed.get(&r) {
if let Some(&popped) = cols.get(&c) {
return popped;
}
}
false
}
fn close(closed: &mut HashMap<i32, HashMap<i32, bool>>, r: i32, c: i32) {
let cols = closed.entry(r).or_default();
cols.insert(c, true);
}
fn add(
cost: i32,
r: i32,
c: i32,
x: i32,
y: i32,
closed: &mut HashMap<i32, HashMap<i32, bool>>,
heap: &mut BinaryHeap<KnightMove>,
) {
if !is_popped(closed, r, c) {
heap.push(KnightMove {
cost,
distance: distance(r, c, x, y),
row: r,
col: c,
});
}
}
fn distance(r: i32, c: i32, x: i32, y: i32) -> i32 {
(i32::abs(x - r) + i32::abs(y - c)) / 3
}
fn main() {
let x = 2;
let y = 1;
let result = min_knight_moves(x, y);
println!("Minimum knight moves: {}", result);
}

c++完整代码如下:
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>
using namespace std;
bool isPoped(unordered_map<int, unordered_set<int>>& closed, int r, int c) {
return closed.count(r) && closed[r].count(c);
}
void close(unordered_map<int, unordered_set<int>>& closed, int r, int c) {
if (!closed.count(r)) {
closed[r] = unordered_set<int>();
}
closed[r].insert(c);
}
int distance(int r, int c, int x, int y);
void add(int cost, int r, int c, int x, int y, unordered_map<int, unordered_set<int>>& closed,
priority_queue<vector<int>, vector<vector<int>>, greater<>>& heap) {
if (!isPoped(closed, r, c)) {
heap.push({ cost, distance(r, c, x, y), r, c });
}
}
int distance(int r, int c, int x, int y) {
return (abs(x - r) + abs(y - c)) / 3;
}
int minKnightMoves(int x, int y) {
priority_queue<vector<int>, vector<vector<int>>, greater<>> heap;
unordered_map<int, unordered_set<int>> closed;
heap.push({ 0, distance(0, 0, x, y), 0, 0 });
int ans = INT_MAX;
while (!heap.empty()) {
vector<int> cur = heap.top();
heap.pop();
int cost = cur[0];
int row = cur[2];
int col = cur[3];
if (isPoped(closed, row, col)) {
continue;
}
if (row == x && col == y) {
ans = cost;
break;
}
close(closed, row, col);
add(cost + 1, row + 2, col + 1, x, y, closed, heap);
add(cost + 1, row + 1, col + 2, x, y, closed, heap);
add(cost + 1, row - 1, col + 2, x, y, closed, heap);
add(cost + 1, row - 2, col + 1, x, y, closed, heap);
add(cost + 1, row - 2, col - 1, x, y, closed, heap);
add(cost + 1, row - 1, col - 2, x, y, closed, heap);
add(cost + 1, row + 1, col - 2, x, y, closed, heap);
add(cost + 1, row + 2, col - 1, x, y, closed, heap);
}
return ans;
}
int main() {
int x = 2;
int y = 1;
int result = minKnightMoves(x, y);
cout << "Minimum number of knight moves: " << result << endl;
return 0;
}

2023-08-16:用go语言如何解决进击的骑士算法问题呢?的更多相关文章
- Oracle存储过程中不支持DML语言的解决方法(针对遇见的DROP关键字)
---存储过程中的原语句: ---删除表 DROP TABLE A_NEWTDDATA; --报错 经查询:存储过程不支持DML语言: 解决方法: execute immediate 'DROP TA ...
- http://www.cnblogs.com/alipayhutu/archive/2012/08/16/2643098.html
http://www.cnblogs.com/alipayhutu/archive/2012/08/16/2643098.html
- 2021.08.16 P1260 工程规划(差分约束)
2021.08.16 P1260 工程规划(差分约束) 重点: 1.跑最短路是为了满足更多约束条件. P1260 工程规划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 造 ...
- 2021.08.16 P1078 文化之旅(最短路)
2021.08.16 P1078 文化之旅(最短路) 题意: n个地,k个信仰,每个地都有自己的信仰,信仰之间会相互排斥,同信仰之间也会相互排斥,有m条路,问从s到t的最短距离是多少? 有一位使者要游 ...
- 2021.08.16 P1300 城市街道交通费系统(dfs)
2021.08.16 P1300 城市街道交通费系统(dfs) P1300 城市街道交通费系统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 城市街道交费系统最近创立了.一 ...
- 2021.08.16 P1363 幻象迷宫(dfs,我感受到了出题人浓浓的恶意)
2021.08.16 P1363 幻象迷宫(dfs,我感受到了出题人浓浓的恶意) P1363 幻象迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 幻象迷宫可以认为是无限 ...
- 2023.1.16[模板]BSGS/exBSGS
2023.1.16 [模板]BSGS/exBSGS 全称Boy Step Girl Step 给定一个质数 p,以及一个整数 a,一个整数 b,现在要求你计算一个最小的非负整数 l, 满足\(a^x ...
- 《用Python解决数据结构与算法问题》在线阅读
源于经典 数据结构作为计算机从业人员的必备基础,Java, c 之类的语言有很多这方面的书籍,Python 相对较少, 其中比较著名的一本 problem-solving-with-algorithm ...
- C语言8大经典排序算法(1)
算法一直是编程的基础,而排序算法是学习算法的开始,排序也是数据处理的重要内容.所谓排序是指将一个无序列整理成按非递减顺序排列的有序序列.排列的方法有很多,根据待排序序列的规模以及对数据的处理的要求,可 ...
- C语言词法分析中的贪心算法
C语言词法分析中的贪心算法 当我们写出a---b这种语句的时候我们应该考虑C语言的编译器是如何去分析这条语句的. C语言对于解决这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多 ...
随机推荐
- 19c上ADG主库sys密码修改会影响备库同步吗?
一套Oracle 19c的ADG集群要修改sys密码,由于之前遇见过11g上sys密码修改导致同步问题的情况,所以改之前特意查了下文档,发现其实12cR2开始,在主库修改密码就会自动同步到备库了,以下 ...
- Caused by: liquibase.exception.ValidationFailedException: Validation Failed:1 change sets check sum
db/changelog/mysql/changelog-0001-307096-1.0.sql::1.0::buoluo.meng was: 8:a5d8f616a121230c204fd2b878 ...
- P8679 [蓝桥杯 2019 省 B] 填空问题 题解
P8679 [蓝桥杯 2019 省 B] 填空问题 题解 题目传送门 欢迎大家指出错误并联系这个蒟蒻 更新日志 2023-05-25 21:02 文章完成 2023-05-27 11:34 文章通过审 ...
- Perceptual Losses 风格迁移论文复现小记
看了一篇李飞飞组的论文 Perceptual Losses for Real-Time Style Transfer and Super-Resolution. 论文地址为:https://arxiv ...
- Java开发面试--群面专区
目录 一.群面背景 二.群面流程 三.群面角色 四.群面细节 五.群面礼仪 六.群面话术 七.个人演讲 八.群面题型 群面也称无领导小组~ 候选人们被要求在一个相对自由的环境中展示他们的能力,并在没有 ...
- 如何用CAN-EYE获取植被参数数据?
本文介绍植被冠层参数计算软件CAN-EYE的具体使用方法. 在文章下载.安装CAN-EYE植被参数工具中,我们介绍了CAN-EYE软件的下载.安装方法:本文就对该软件的具体使用方法进行介绍. ...
- C# 在流行度指数上将超过Java
2023年10月最新的TIOBE编程语言流行指数表明:C#和Java之间的差距从未如此之小,目前,差异仅为1.2%,如果趋势保持这种状态,C#将在大约2个月内超过Java,TIOBE Software ...
- js前端操作,c#后端下发xml文件
前端: var xmlLanguageDoc; $.ajax({ url: "/GiveMeXML",//此处可随意定义,不一定是路径.在c# ,请求被捕获后,由c ...
- 字符串小记 I:基本结构与简单匹配(更新中)
0.一些定义 在开始之前,我们先给出一些关于字符串的定义: 记 \(|S|\) 表示字符串 \(S\) 的长度,\(S_i\) 表示该字符串中第 \(i\) 位的字符,\(S_{l,r}\) 表示该字 ...
- gitlab : You won`t be able to pull or push project code via SSH until you add an SSH key to your profile(导致的问题:合并不了代码)
gitlab : You won`t be able to pull or push project code via SSH until you add an SSH key to your pro ...