📜  在银行中找到与守卫的最短距离(1)

📅  最后修改于: 2023-12-03 14:51:34.109000             🧑  作者: Mango

在银行中找到与守卫的最短距离

在银行中,保安守卫着入口,盯着每个人进出,并确保行为正常。现在,你需要编写一段程序来帮助每个人找到与守卫的最短距离。

程序设计

为了解决这个问题,我们可以使用广度优先搜索算法。我们先将保安视为起点,每个人的位置视为终点,然后搜索出最短距离。

数据结构

我们需要定义以下结构:

  • Bank:表示银行。包括高度和宽度两个属性 hw ,以及 starttargets 两个点的信息。其中,start 表示保安的位置,targets 表示每个人的位置。
  • Point:表示地图上的一个点。包括坐标 xy ,以及当前点到起点的距离 dist
  • Queue:我们使用队列来辅助实现广度优先搜索。
class Bank:
    def __init__(self, h: int, w: int, start: tuple, targets: List[tuple]):
        self.h = h
        self.w = w
        self.start = start
        self.targets = targets


class Point:
    def __init__(self, x: int, y: int, dist: int):
        self.x = x
        self.y = y
        self.dist = dist


class Queue:
    def __init__(self):
        self.queue = []

    def put(self, p: Point):
        self.queue.append(p)

    def get(self) -> Point:
        if len(self.queue) > 0:
            return self.queue.pop(0)
        return None

    def is_empty(self) -> bool:
        return len(self.queue) == 0
算法实现

我们使用 BFS 来实现广度优先搜索。

为了避免重复访问同一节点,我们需要设置一个 visited 的标记来记录访问过的节点。

在计算起点与每个人的最短距离时,我们只需要计算直线距离即可。因此,在计算两个点之间的直线距离时,我们可以使用欧几里得距离公式:

$$ distance = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} $$

import math

def bfs(bank: Bank) -> int:
    queue = Queue()
    visited = set()
    start = Point(bank.start[0], bank.start[1], 0)
    queue.put(start)
    visited.add((start.x, start.y))

    while not queue.is_empty():
        point = queue.get()
        if (point.x, point.y) in bank.targets:
            return point.dist

        for next_point in get_next_points(point, bank):
            if (next_point.x, next_point.y) not in visited:
                queue.put(next_point)
                visited.add((next_point.x, next_point.y))

    return -1


def get_next_points(point: Point, bank: Bank) -> List[Point]:
    # 上下左右四个方向
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    next_points = []

    for direction in directions:
        next_x, next_y = point.x + direction[0], point.y + direction[1]
        if 0 <= next_x < bank.h and 0 <= next_y < bank.w:
            next_point = Point(next_x, next_y, point.dist + 1)
            next_points.append(next_point)

    # 加入每个人的位置
    for tgt in bank.targets:
        distance = math.sqrt((point.x - tgt[0]) ** 2 + (point.y - tgt[1]) ** 2)
        if distance < 2:
            next_point = Point(tgt[0], tgt[1], point.dist + 1)
            next_points.append(next_point)

    return next_points
使用示例

下面是一个使用示例:

if __name__ == '__main__':
    bank = Bank(5, 5, (0, 0), [(1, 2), (2, 2)])
    length = bfs(bank)
    print(length)

这里,我们给出了一个 5x5 的银行地图,其中保安的位置是 (0, 0),两名顾客的位置分别是 (1, 2)(2, 2)。我们调用 bfs 函数,即可得到保安与两名顾客之间的最短距离。

返回的代码片段

# 在银行中找到与守卫的最短距离

在银行中,保安守卫着入口,盯着每个人进出,并确保行为正常。现在,你需要编写一段程序来帮助每个人找到与守卫的最短距离。

## 程序设计

为了解决这个问题,我们可以使用广度优先搜索算法。我们先将保安视为起点,每个人的位置视为终点,然后搜索出最短距离。

### 数据结构

我们需要定义以下结构:

- `Bank`:表示银行。包括高度和宽度两个属性 `h` 和 `w` ,以及 `start` 和 `targets` 两个点的信息。其中,`start` 表示保安的位置,`targets` 表示每个人的位置。
- `Point`:表示地图上的一个点。包括坐标 `x` 和 `y` ,以及当前点到起点的距离 `dist`。
- `Queue`:我们使用队列来辅助实现广度优先搜索。

```python
class Bank:
    def __init__(self, h: int, w: int, start: tuple, targets: List[tuple]):
        self.h = h
        self.w = w
        self.start = start
        self.targets = targets


class Point:
    def __init__(self, x: int, y: int, dist: int):
        self.x = x
        self.y = y
        self.dist = dist


class Queue:
    def __init__(self):
        self.queue = []

    def put(self, p: Point):
        self.queue.append(p)

    def get(self) -> Point:
        if len(self.queue) > 0:
            return self.queue.pop(0)
        return None

    def is_empty(self) -> bool:
        return len(self.queue) == 0
算法实现

我们使用 BFS 来实现广度优先搜索。

为了避免重复访问同一节点,我们需要设置一个 visited 的标记来记录访问过的节点。

在计算起点与每个人的最短距离时,我们只需要计算直线距离即可。因此,在计算两个点之间的直线距离时,我们可以使用欧几里得距离公式:

$$ distance = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} $$

import math

def bfs(bank: Bank) -> int:
    queue = Queue()
    visited = set()
    start = Point(bank.start[0], bank.start[1], 0)
    queue.put(start)
    visited.add((start.x, start.y))

    while not queue.is_empty():
        point = queue.get()
        if (point.x, point.y) in bank.targets:
            return point.dist

        for next_point in get_next_points(point, bank):
            if (next_point.x, next_point.y) not in visited:
                queue.put(next_point)
                visited.add((next_point.x, next_point.y))

    return -1


def get_next_points(point: Point, bank: Bank) -> List[Point]:
    # 上下左右四个方向
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    next_points = []

    for direction in directions:
        next_x, next_y = point.x + direction[0], point.y + direction[1]
        if 0 <= next_x < bank.h and 0 <= next_y < bank.w:
            next_point = Point(next_x, next_y, point.dist + 1)
            next_points.append(next_point)

    # 加入每个人的位置
    for tgt in bank.targets:
        distance = math.sqrt((point.x - tgt[0]) ** 2 + (point.y - tgt[1]) ** 2)
        if distance < 2:
            next_point = Point(tgt[0], tgt[1], point.dist + 1)
            next_points.append(next_point)

    return next_points
使用示例

下面是一个使用示例:

if __name__ == '__main__':
    bank = Bank(5, 5, (0, 0), [(1, 2), (2, 2)])
    length = bfs(bank)
    print(length)

这里,我们给出了一个 5x5 的银行地图,其中保安的位置是 (0, 0),两名顾客的位置分别是 (1, 2)(2, 2)。我们调用 bfs 函数,即可得到保安与两名顾客之间的最短距离。