如何将Dijkstra算法应用于机械臂移箱的最低能耗路径求解
给定一台堆叠箱子的机械臂,要求每堆箱子最多3个,需按重量顺序(从下到上重量递减)放置在左侧初始栈中。机械臂可移动1格或4格,支持左右双向移动。
初始配置:
| ------ | | | _10_ _30_ ____ _10_ ____ | _40_ ____ _20_ ____ _30_
移动能耗规则:
- 每移动1格基础能耗为1,移动超过2格时按移动距离的75%计算;
- 每10磅重量增加1能耗,例如移动40磅箱子2格的能耗为
2*0.75 + 40/10 = 5.5。
目标最终配置:
| ------ 10 10 | | 30 20 | _40_ _30_ ____ ____ ____ | ____ ____ ____ ____ ____
需使用Dijkstra算法从初始配置出发,实现机械臂以最低能耗完成任务。已知Dijkstra算法原理,但不知如何将该问题建模为有限图,求解决思路。
1. 定义图的节点(状态)
每个节点代表系统的完整状态,包含三个核心信息,且所有状态数量有限(箱子总数固定,每堆最多3个):
- 所有栈的堆叠情况:用元组列表表示每个栈的箱子(从下到上),例如初始状态可表示为
([10], [30], [], [10], [], [40], [], [20], [], [30])(对应10个栈的顺序); - 机械臂当前位置:用栈的索引(0-9)表示;
- 机械臂持有状态:记录持有箱子的重量(0表示未持有)。
2. 定义图的边(状态转移)
每条边对应一次合法操作,边的权重为该操作的能耗,合法操作分为三类:
(1)抓取箱子
当机械臂位于非空栈上方且未持有箱子时,可抓取栈顶箱子。状态变化为:目标栈移除顶部箱子,机械臂持有该箱子的重量。此操作能耗为0(题目未提及抓取能耗)。
(2)放置箱子
当机械臂持有箱子,且目标栈箱子数量小于3,同时满足堆叠规则(若目标栈非空,放置的箱子重量需小于等于栈顶箱子重量),可将箱子放置到目标栈顶部。状态变化为:目标栈添加该箱子,机械臂恢复未持有状态。此操作能耗为0(题目未提及放置能耗)。
(3)移动机械臂
机械臂可从当前位置i移动到i±1或i±4的合法栈位置(索引0-9),能耗计算规则:
- 计算移动距离
d = |目标位置 - 当前位置|; - 基础能耗:若
d > 2则为d * 0.75,否则为d * 1; - 重量附加能耗:若持有重量为
w的箱子,附加w / 10; - 总能耗 = 基础能耗 + 重量附加能耗。
3. 初始化Dijkstra算法
- 起始节点:初始配置对应的状态,即各栈堆叠情况如初始配置,机械臂未持有箱子(重量0),初始位置可设为任意合法栈索引(通常选有箱子的栈,比如初始配置中索引5的栈)。
- 目标节点:所有满足目标配置的状态,即前两个栈为
([40,30,10], [30,20,10]),其余栈为空,且机械臂未持有箱子(位置任意)。
4. 状态哈希与去重
将状态转换为可哈希的格式(比如把栈的列表转为元组列表),用字典记录每个状态的最短能耗,避免重复处理同一状态。例如状态可表示为(tuple(tuple(stack) for stack in stacks), arm_pos, held_weight)。
5. 优先级队列的使用
采用最小堆作为优先级队列,每次取出当前能耗最低的状态,遍历所有合法操作生成新状态,计算新能耗(当前能耗 + 操作能耗)。若新状态未被记录,或新能耗低于已记录的最短能耗,则更新记录并将新状态加入队列。
内容的提问来源于stack exchange,提问作者AnalyticMind

