我正在编程中做作业,但我不知道如何解决此问题:
我们有一组n个权重,我们将它们逐个缩放,直到使用了所有权重。我们还有n个字母的字符串“ R”或“ L”,这表示那一刻哪支笔较重,它们不能保持平衡。没有相同质量的砝码。计算我们必须按什么顺序将权重放在比例尺和平底锅上。
目标是找到按比例放置权重的顺序,以便尊重输入字符串。
输入:数字0 输出:在n行中,放置砝码,并在“ R”或“ L”侧放置砝码。如果有很多,则输出其中任何一个。 示例1: 输入: 输出: 示例2: 输入: 输出: 示例3: 输入: 输出: 我已经尝试使用递归来计算它,但是没有成功。有人可以帮我解决这个问题,还是给我提示如何解决。 3
10 20 30
LRL
10 L
20 R
30 L
3
10 20 30
LLR
20 L
10 R
30 R
5
10 20 30 40 50
LLLLR
50 L
10 L
20 R
30 R
40 R
答案 0 :(得分:1)
由于您没有显示自己的任何代码,因此我将为您提供一些没有代码的想法。如果您需要更多帮助,请显示更多工作,然后我将向您显示可解决您问题的Python代码。
您的问题适合backtracking。维基百科对此算法的定义是
回溯是一种通用算法,用于查找某些computational problems,尤其是constraint satisfaction problems的所有(或某些)解决方案,该算法会逐步为解决方案构建候选,并尽快放弃候选(“回溯”)因为它确定候选人不可能完成有效的解决方案。
和
回溯仅适用于那些承认“部分候选解决方案”概念的问题,并且需要相对快速地测试它是否可以完成为有效的解决方案。
您的问题满足这些要求。在每个阶段,您需要选择剩余的砝码之一和秤的两个秤盘之一。将选定的砝码放在选定的秤盘上时,可以确定是否满足输入字符串中的相应字母。如果不是,则拒绝选择重量和平移。如果是这样,请继续选择另一个砝码和平移。
您的总体例行程序首先输入并准备数据。然后,它调用一个递归例程,该例程在每个级别选择一个权重和一个平移。每个级别所需的某些信息可以放入可变的全局变量中,但是如果您将所有所需的信息作为参数传递,则将更加清楚。每次调用递归例程都需要传递:
您的递归基本情况是未使用的权重和未使用的字母为空。然后,您已完成搜索,可以打印解决方案并退出程序。否则,您将遍历未使用的砝码之一和秤盘的所有组合。对于每种组合,请计算将重物放在该秤盘上会产生的新失衡。如果新的不平衡与相应的字母一致,请使用适当修改的参数递归调用例程。如果没有,则对此重量和平移不进行任何操作。
在编码之前,您还有一些选择要选择,例如未使用权重的数据结构。告诉我您自己的一些编码工作,然后我将为您提供Python代码。
请注意,对于许多重量来说,这可能会很慢。对于n
权重和两个平底锅,将权重放置在平底锅上的方式总数为n! * 2**n
(即阶乘和幂)。对于n = 50
以上的3e79
来说,太大了。回溯避免了大多数选择,因为选择会尽快被拒绝,但是我的算法可能仍然很慢。可能有比回溯更好的算法,但我看不到。您的问题似乎旨在通过回溯处理。
现在您已经付出了更多努力,这是我未优化的Python 3代码。尽管您为第三个示例提供了不同的有效解决方案,但该方法适用于您提供的所有示例。
def weights_on_pans():
def solve(unused_weights, unused_tilts, placement, imbalance):
"""Place the weights on the scales using recursive
backtracking. Return True if successful, False otherwise."""
if not unused_weights:
# Done: print the placement and note that we succeeded
for weight, pan in placement:
print(weight, 'L' if pan < 0 else 'R')
return True # success right now
tilt, *later_tilts = unused_tilts
for weight in unused_weights:
for pan in (-1, 1): # -1 means left, 1 means right
new_imbalance = imbalance + pan * weight
if new_imbalance * tilt > 0: # both negative or both positive
# Continue searching since imbalance in proper direction
if solve(unused_weights - {weight},
later_tilts,
placement + [(weight, pan)],
new_imbalance):
return True # success at a lower level
return False # not yet successful
# Get the inputs from standard input. (This version has no validity checks)
cnt_weights = int(input())
weights = {int(item) for item in input().split()}
letters = input()
# Call the recursive routine with appropriate starting parameters.
tilts = [(-1 if letter == 'L' else 1) for letter in letters]
solve(weights, tilts, [], 0)
weights_on_pans()
我看到的加快代码速度的主要方法是避免在内循环中对O(n)
的调用中进行solve
操作。这意味着可能会更改unused_weights
的数据结构,并更改placement
和unused_tilts
/ later_tilts
的修改方式以使用O(1)
操作。这些更改会使代码复杂化,这就是为什么我不这样做。