Javascript 算法将球从一组桶移动到另一组桶,移动次数最少,给定一台机器可以在一次移动中移动无限球

Javascript 算法将球从一组桶移动到另一组桶,移动次数最少,给定一台机器可以在一次移动中移动无限球,javascript,algorithm,math,Javascript,Algorithm,Math,我的一个朋友提出了一个问题,你有n个桶(a,b,c,…,n),每个桶占你的总球数的一定百分比。然后,在问题结束时,您将得到每个桶应该有多少个球的明细。您还可以在一次移动中,将无限球从一个单一铲斗移动到另一个单一铲斗(例如,10个球从铲斗a移动到铲斗C)。你会使用什么算法来确保你总是有尽可能少的移动次数 我被这个难住了。看起来它可以用欧几里得算法的扩展来解决,但我完全不确定我将如何解决这个问题。我测试了两个最大/完美的问题桶之间的匹配的明显答案,但这不起作用。任何提示都会有帮助。我已经删除了以前的

我的一个朋友提出了一个问题,你有n个桶(a,b,c,…,n),每个桶占你的总球数的一定百分比。然后,在问题结束时,您将得到每个桶应该有多少个球的明细。您还可以在一次移动中,将无限球从一个单一铲斗移动到另一个单一铲斗(例如,10个球从铲斗a移动到铲斗C)。你会使用什么算法来确保你总是有尽可能少的移动次数


我被这个难住了。看起来它可以用欧几里得算法的扩展来解决,但我完全不确定我将如何解决这个问题。我测试了两个最大/完美的问题桶之间的匹配的明显答案,但这不起作用。任何提示都会有帮助。

我已经删除了以前的答案。你考虑过子集和问题吗?我不确定它是否能为整个问题找到最佳解决方案,但这里是想法

对于每个铲斗,让差值=(目标球数)-(给定球数)。设P为一组正差值,N为一组负差值的绝对值。
从两个集合中选择下一个最大数,并在相反的集合中查找最小子集和。如果找到子集,则移动球。否则,从集合中查找下一个最大数的子集和

查找完子集后,考虑剩余的桶。在两个相反组的剩余铲斗之间移动钢球。这将为其中一个桶创建新的差异。可以用新的差形成新的匹配子集和。使用新形成的差再次搜索子集和。重复此操作,直到所有铲斗都达到目标球数


我不确定是否总是考虑最大的桶可以保证最佳性。如果您找到了正确的解决方案,请告诉我们

使用启发式函数在可能移动的图表上使用A*:与目标桶不同的桶数除以2。也就是说,
b/2
其中,
b
是桶中包含错误数量的桶数

A*通常被认为是游戏中类似路由单元的寻路算法,但它适用于任何图形,您可以找到一种启发式算法,该算法永远不会高估到目标节点的距离。最重要的是,装备了这种启发式算法的*将始终找到最短路径。借用博弈论,我们可以想象一个图,由链接连接的节点,其中每个节点是桶中球的可能分布,每个链接代表机器可以进行的合法移动。开始节点是球的开始分布。您的目标节点是球的目标分布

使用此图,我们可以应用呼吸优先搜索和等待,直到我们碰巧访问目标节点。这将为我们提供从起始分布到目标分布的最短移动集,因为这是一个呼吸优先的搜索。(在这种情况下,这或多或少相当于Dijkstra的算法,因为每个移动的成本(长度)与1个移动相同)

然而,我们可以做得更好。A*使用启发式搜索图。具体地说,它类似于呼吸优先搜索,除了A*下一次访问距离起始节点最近的未访问节点之外,A*下一次访问未访问节点,该节点最小化
g(n)+h(n)
,其中
g(n)
是从未访问节点
n
到起始节点和
h(n)的长度
是未访问节点到目标距离的启发式方法。这意味着,当我们首先检查通往目标的明显路径时,我们会“远离”目标,从而减少搜索最优路径的计算时间。数学上已经证明,如果你能找到一个可接受的启发式,A*将为你提供从起始节点到目标节点的最佳路径,这意味着一个启发式永远不会高估到目标的距离。例如,在视频游戏中,两点之间的可行走路径长度始终大于或等于“按乌鸦距离”的距离。尽管我们的图不是表示物理空间的图,但我们仍然可以找到一个可接受的启发式

一次移动最多可以使两个桶具有正确的球数,因为一次移动最多只能影响两个桶。因此,例如,如果我们数一数我们的水桶,发现4个水桶中的球的数量错误,那么我们知道至少需要2次移动。可能更多,但不能少于2

让我们的启发式是“具有错误球数的桶数除以2”

我们的启发式算法不会高估获得所需球数所需的移动次数,因为即使是最好的移动方式,只要你配合我们的启发式算法,你就可以匹配快乐对。我们的启发式算法经常低估移动,但这没关系,计算只需要更长的时间,但不会得到错误的结果,并且移动的结果计划仍然是最短的。因此,我们的启发式是可以接受的,这意味着它永远不会高估移动的数量

因此,A*采用“具有错误球数的桶数除以2”的启发式,将始终找到到达分布的最短移动次数


也许可以找到更好的启发式方法,如果是这样,那么搜索速度会更快。这只是我想到的第一个启发式方法。

如果你能把桶配对,那么n/2次移动就足够了。这是正确的,但是如果有x个桶的球太多,y个球太少,那么你只需要在MAX(x,y)和x+y-1次移动之间,ne