java - Java - 使用 bellman-held-karp 算法的基于规则的排序
问题描述
我在 CS SE 上问了以下问题,但不知道如何在 java 中实现答案(更不用说弄清楚它实际上在说什么):
我想在花园里种一排。某些植物对某些植物有益而对其他植物有害,我正在尝试找到植物的最佳顺序:最相邻的朋友,没有相邻的敌人,如下表所定义(我各有一个):
Num Vegetable Friends Foes
1 Watermelon 7,4,3 8,6
2 Tomatoes 9,8,6,5,1 7
3 Sunflowers 7,6,11
4 Zucchini 9,7,3
5 Eggplant 9,6,2 7,10
6 Cucumbers 9,7,3 8,1
7 Corn 8,6,4,3,1 5,2
8 Cantaloup 7,4,3 6,1
9 Bell peppers 6,5,11,10,2
10 Swiss chard 2 5
11 Rhubarb 9,3
如何找到安排?
“Jakube”回答:
您可以通过简单地遍历所有 n! 不同的排列,并检查每个排列是否允许以及它有多好。这具有复杂性 O(n⋅n!)。
Bellman-Held-Karp 算法的变体将更快(但仍然是指数复杂度)。计算每一对 (V,v),其中 V 是所有蔬菜的子集,并且 v∈V,如果有可能以一种方式排列蔬菜 V,使得 v 是最后一个并且它的最佳值是什么。您可以为此函数定义一个递归公式,并应用动态编程,就像在 BHK 算法中一样。这应该在 O(n 2 ⋅2n) 内运行。”
我最初问这个问题是因为我每个人都有一个,但现在意识到我需要一个可以偶尔重复的答案。我不确定他给出的答案是否适用于我拥有多个给定植物的情况。
解决方案
我知道你标记了这个 Java,但这里有一些 Python 实现了那个动态程序。
import collections
Plant = collections.namedtuple("Plant", ("id", "name", "friends", "foes"))
def extend(first_plant, result):
objective, other_plants = result
return (
(first_plant.id in other_plants[0].friends)
+ (other_plants[0].id in first_plant.friends)
+ objective,
[first_plant] + other_plants,
)
def best_order_recursive(first_plant, other_plants, cache):
if not other_plants:
return 0, [first_plant]
cache_key = (first_plant.id, frozenset(plant.id for plant in other_plants))
if cache is None:
cache = {}
else:
cache_value = cache.get(cache_key)
if cache_value is not None:
return cache_value
value = max(
(
extend(
first_plant,
best_order_recursive(
next_plant, other_plants[:i] + other_plants[i + 1 :], cache
),
)
for (i, next_plant) in enumerate(other_plants)
if first_plant.id not in next_plant.foes
and next_plant.id not in first_plant.foes
),
default=(float("-inf"), [first_plant]),
)
cache[cache_key] = value
return value
def best_order(plants):
cache = {}
return max(
best_order_recursive(first_plant, plants[:i] + plants[i + 1 :], cache)
for (i, first_plant) in enumerate(plants)
)
def main():
objective, plants = best_order(
[
Plant(1, "Watermelon", {7, 4, 3}, {8, 6}),
Plant(2, "Tomatoes", {9, 8, 6, 5, 1}, {7}),
Plant(3, "Sunflowers", {7, 6, 11}, set()),
Plant(4, "Zucchini", {9, 7, 3}, set()),
Plant(5, "Eggplant", {9, 6, 2}, {7, 10}),
Plant(6, "Cucumbers", {9, 7, 3}, {8, 1}),
Plant(7, "Corn", {8, 6, 4, 3, 1}, {5, 2}),
Plant(8, "Cantaloupe", {7, 4, 3}, {6, 1}),
Plant(9, "Bell peppers", {6, 5, 11, 10, 2}, set()),
Plant(10, "Swiss chard", {2}, {5}),
Plant(11, "Rhubarb", {9, 3}, set()),
]
)
print(objective)
print(*(plant.name for plant in plants), sep=", ")
if __name__ == "__main__":
main()
推荐阅读
- google-cloud-firestore - 保存离线 webapp Firestore 的数据
- javascript - 如何使用 json 服务器达到特定的端点
- reactjs - 使用 TypeScript 和 ReactJS 加载 JSON 会给出“找不到文件”
- python - 处理来自 json 的数据以反映每个条目的单个值
- embedded-linux - devtool upgrade 错误:配方已经在您的工作区中
- angular - 如何验证用户是否已登录
- r - 正则表达式“字符串中的每个字符都是数字吗?”
- python-3.x - Python:如何模拟多次调用的异步方法?
- python - Python @property 无法按我的意愿工作
- python - 如何避免多次尝试,除了块python