3812 机器人走迷宫(枚举 + 全排列)

1. 问题描述:

有一个 n × m 个单元格构成的迷宫,其中空单元格用 . 表示,障碍物用 # 表示。迷宫中有一个机器人,它的起点位置用 S 表示,目标位置用 E 表示,这两个地点均没有障碍。机器人只能沿上下左右四个方向移动。给定一串由数字 0∼3 构成的字符串,表示机器人的行动指令列表。机器人将按照列表中的指令,依次进行移动。在执行指令的过程中:
如果机器人走出迷宫边界或者碰到障碍物,则机器人会损坏。
如果机器人到达目标位置,则停止行动,不再接受后续指令。
现在,哪个数字(0∼3)对应哪种行动(上下左右)还未分配。
请问,共有多少种分配方案,能够使得机器人顺利到达目标位置。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。每组数据第一行包含两个整数 n 和 m。接下来 n 行,每行包含 m 个字符,表示迷宫。所有字符均为 ., #,,S, E 之一,其中 S 和 E 出现且仅出现一次。最后一行包含一个字符串 s 表示指令列表,每个字符均为 0∼3 之一。

输出格式

每组数据输出一行结果,表示能够使得机器人顺利到达目标位置的行动指令分配方案数量。

数据范围

前三个测试点满足 2 ≤ n, m ≤ 10。
所有测试点满足 1 ≤ T ≤ 10,2 ≤ n,m ≤ 50,1 ≤ |s| ≤ 100。
同一测试点内,所有 n × m 的和不超过 2500。

输入样例:

2
5 6
.....#
S....#
.#....
.#....
...E..
333300012
6 6
......
......
..SE..
......
......
......
01232123212302123021

输出样例:

1
14
来源:https://www.acwing.com/problem/content/description/3815/

2. 思路分析:

因为0~3对应的上下左右四个方向是不确定的所以我们可以枚举所有的可能,总的方案数目为4的全排列也即有24种可能,所以我们可以枚举24种不同的方向,可以使用递归交换元素的方法生成[0,1,2,3]的全排列,然后枚举所有的排列,判断s按照当前排列对应的方向执行是否可以到达终点,如果可以到达终点那么计数加1即可。

3. 代码如下:

from typing import List


class Solution:
    pos = [[0, 1], [0, -1], [1, 0], [-1, 0]]

    # 交换元素生成全排列
    def get(self, k: int, a: List[int], res: List[List[int]]):
        if k == 4:
            # a[:]为拷贝a的副本, 将其添加到res中
            res.append(a[:])
            return
        for i in range(k, 4):
            a[i], a[k] = a[k], a[i]
            self.get(k + 1, a, res)
            # 恢复现场
            a[i], a[k] = a[k], a[i]

    def check(self, n: int, m: int, x: List[int], s: str, start: List[int], end: List[int], g: List[List[str]]):
        a, b = start[0], start[1]
        for i in range(len(s)):
            k = int(s[i])
            a, b = a + self.pos[x[k]][0], b + self.pos[x[k]][1]
            if a < 0 or a >= n or b < 0 or b >= m or g[a][b] == "#": return False
            # 说明到达了终点
            if a == end[0] and b == end[1]: return True
        return a == end[0] and b == end[1]

    def process(self):
        a = [0, 1, 2, 3]
        res = list()
        # 生成a的所有全排列
        self.get(0, a, res)
        T = int(input())
        while T:
            n, m = map(int, input().split())
            g = list()
            # start, end记录起点和终点的坐标
            start, end = [-1, -1], [-1, -1]
            for i in range(n):
                s = input()
                g.append(list(s))
                for j in range(m):
                    if s[j] == "S":
                        start[0], start[1] = i, j
                    if s[j] == "E":
                        end[0], end[1] = i, j
            s = input()
            count = 0
            for x in res:
                # 判断当前设置的方向是否可以到达终点
                if self.check(n, m, x, s, start, end, g):
                    count += 1
            print(count)
            T -= 1


if __name__ == '__main__':
    Solution().process()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
强化学习机器人迷宫是一个经典的强化学习问题。在这个问题中,机器人需要在一个迷宫中找到出口。机器人可以采取不同的动作,例如向上、向下、向左或向右移动。机器人的目标是找到迷宫的出口,并且在此过程中最小化花费的步数。 为了实现这个问题,我们可以使用 Python 中的强化学习库,例如 OpenAI Gym 或者 PyTorch。我们需要定义一个 Robot 类,这个类将会实现机器人的移动和学习函数。在学习函数中,我们需要实现强化学习算法,例如 Q-learning 或者 Deep Q-Networks(DQN)算法。 在实现机器人迷宫的过程中,我们需要使用迷宫类 Maze 来随机生成一个迷宫。我们可以使用基础搜索算法或者 DQN 算法来训练机器人。在基础搜索算法中,我们可以使用广度优先搜索(BFS)或深度优先搜索(DFS)算法来搜索迷宫。在 DQN 算法中,我们需要使用神经网络来估计每个动作的 Q 值,并且使用经验回放和目标网络来训练神经网络。 以下是一个基于 PyTorch 和 DQN 算法的机器人迷宫的示例代码: ```python import os import random import numpy as np import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from collections import deque from maze import Maze class DQNAgent: def __init__(self, state_size, action_size): self.state_size = state_size self.action_size = action_size self.memory = deque(maxlen=2000) self.gamma = 0.95 self.epsilon = 1.0 self.epsilon_min = 0.01 self.epsilon_decay = 0.995 self.learning_rate = 0.001 self.model = self._build_model() def _build_model(self): model = nn.Sequential( nn.Linear(self.state_size, 64), nn.ReLU(), nn.Linear(64, 64), nn.ReLU(), nn.Linear(64, self.action_size) ) optimizer = optim.Adam(model.parameters(), lr=self.learning_rate) model.compile(loss='mse', optimizer=optimizer) return model def remember(self, state, action, reward, next_state, done): self.memory.append((state, action, reward, next_state, done)) def act(self, state): if np.random.rand() <= self.epsilon: return random.randrange(self.action_size) else: return np.argmax(self.model.predict(state)) def replay(self, batch_size): minibatch = random.sample(self.memory, batch_size) for state, action, reward, next_state, done in minibatch: target = reward if not done: target = (reward + self.gamma * np.amax(self.model.predict(next_state)[0])) target_f = self.model.predict(state) target_f[0][action] = target self.model.fit(state, target_f, epochs=1, verbose=0) if self.epsilon > self.epsilon_min: self.epsilon *= self.epsilon_decay class Robot: def __init__(self, maze_size): self.maze = Maze(maze_size=maze_size) self.state_size = 2 self.action_size = 4 self.agent = DQNAgent(self.state_size, self.action_size) def run(self, episodes): for e in range(episodes): state = self.maze.reset() state = np.reshape(state, [1, self.state_size]) done = False i = 0 while not done: action = self.agent.act(state) next_state, reward, done = self.maze.step(action) next_state = np.reshape(next_state, [1, self.state_size]) self.agent.remember(state, action, reward, next_state, done) state = next_state i += 1 print("episode: {}/{}, steps: {}" .format(e, episodes, i)) if len(self.agent.memory) > 32: self.agent.replay(32) robot = Robot(maze_size=10) robot.run(episodes=1000) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值