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语言如何解决进击的骑士算法问题呢?的更多相关文章

  1. Oracle存储过程中不支持DML语言的解决方法(针对遇见的DROP关键字)

    ---存储过程中的原语句: ---删除表 DROP TABLE A_NEWTDDATA; --报错 经查询:存储过程不支持DML语言: 解决方法: execute immediate 'DROP TA ...

  2. http://www.cnblogs.com/alipayhutu/archive/2012/08/16/2643098.html

    http://www.cnblogs.com/alipayhutu/archive/2012/08/16/2643098.html

  3. 2021.08.16 P1260 工程规划(差分约束)

    2021.08.16 P1260 工程规划(差分约束) 重点: 1.跑最短路是为了满足更多约束条件. P1260 工程规划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 造 ...

  4. 2021.08.16 P1078 文化之旅(最短路)

    2021.08.16 P1078 文化之旅(最短路) 题意: n个地,k个信仰,每个地都有自己的信仰,信仰之间会相互排斥,同信仰之间也会相互排斥,有m条路,问从s到t的最短距离是多少? 有一位使者要游 ...

  5. 2021.08.16 P1300 城市街道交通费系统(dfs)

    2021.08.16 P1300 城市街道交通费系统(dfs) P1300 城市街道交通费系统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 城市街道交费系统最近创立了.一 ...

  6. 2021.08.16 P1363 幻象迷宫(dfs,我感受到了出题人浓浓的恶意)

    2021.08.16 P1363 幻象迷宫(dfs,我感受到了出题人浓浓的恶意) P1363 幻象迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 幻象迷宫可以认为是无限 ...

  7. 2023.1.16[模板]BSGS/exBSGS

    2023.1.16 [模板]BSGS/exBSGS 全称Boy Step Girl Step 给定一个质数 p,以及一个整数 a,一个整数 b,现在要求你计算一个最小的非负整数 l, 满足\(a^x ...

  8. 《用Python解决数据结构与算法问题》在线阅读

    源于经典 数据结构作为计算机从业人员的必备基础,Java, c 之类的语言有很多这方面的书籍,Python 相对较少, 其中比较著名的一本 problem-solving-with-algorithm ...

  9. C语言8大经典排序算法(1)

    算法一直是编程的基础,而排序算法是学习算法的开始,排序也是数据处理的重要内容.所谓排序是指将一个无序列整理成按非递减顺序排列的有序序列.排列的方法有很多,根据待排序序列的规模以及对数据的处理的要求,可 ...

  10. C语言词法分析中的贪心算法

    C语言词法分析中的贪心算法 当我们写出a---b这种语句的时候我们应该考虑C语言的编译器是如何去分析这条语句的. C语言对于解决这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多 ...

随机推荐

  1. c语言代码练习--函数

    函数: 一,概念: 1,在计算科学中,子程序(英语:Subroutione,procedure,function,rotine,method.subprogram,callable unit),是一个 ...

  2. 详解RecyclerView的预布局

    概述 RecyclerView 的预布局用于 Item 动画中,也叫做预测动画.其用于当 Item 项进行变化时执行的一次布局过程(如添加或删除 Item 项),使 ItemAnimator 体验更加 ...

  3. ProcessingJS

    ProcessingJS 图形 rect(x, y, w, h)(在新窗口中打开) ellipse(x, y, w, h) triangle(x1, y1, x2, y2, x3, y3) line( ...

  4. Hugging Face 分词器新增聊天模板属性

    一个幽灵,格式不正确的幽灵,在聊天模型中游荡! 太长不看版 现存的聊天模型使用的训练数据格式各各不同,我们需要用这些格式将对话转换为单个字符串并传给分词器.如果我们在微调或推理时使用的格式与模型训练时 ...

  5. 手写商用Java虚拟机HotSpot,疯狂磨砺技术中

    在当前Java行业激烈竞争的形式下,唯有掌握技术,心中才不能慌.在多年前,我就开始苦练底层技术,但是眼看百遍也不如手过一遍,所以我打算把虚拟机的精华实现部分用手敲出来,这个过程注定不会轻松,但是心态不 ...

  6. windows文件搜索;文件预览;全文搜索,只需myso就够了

    简介   现在提到windows文件搜索,大家可能会想到Everything.Listary.AnyTXT这三款工具,它们各有自己的专长,不能相互替代,需要安装至少两款才能高效的搜索电脑文件.现在向大 ...

  7. 大立科技DM63红外相机SDK开发Ⅰ-连接仪器

    1.开发准备 为了方便发开,需要下载Visual Studio,本开发基于Visual Studio 2022,使用C++. 通过Visual Studio创建好项目后,将DMSDK V1.16.3内 ...

  8. FC 交换机基础配置

    目录 Primera600 存储服务器 FC 交换机 交换机信息查看 交换机配置管理 用户管理 以太网配置 端口配置管理 别名配置 证书管理 角色管理 Zone 管理 参考网址 Primera600 ...

  9. VUE同级组件之前方法调用

    实现:Index.vue页面调用nav.vue页面里的getLeftMenu()方法 一.首先先建一个公共文件,命名eventBus.js,内空为: import Vue from 'vue'expo ...

  10. 工厂模式(Factory Method)

    模式定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method使得一个类的实例化延迟(目的:解耦)到子类. 要点总结 Factory Method模式用于隔离类对象的使用 ...