我被分配了一项任务-解决以下编程难题:
山羊
乔治和他的山羊群在河岸边。他想用重量有限的筏子(不超过 K 条)和山羊一起穿过河。他的山羊不同,体重也不同。他想计算出筏子的最小承载能力是多少,才能使所有 N 只山羊在不超过 K 条路线的情况下穿过河道。
但是,他有必须遵守的规则:
在每个过程中,他首先将最重的山羊放到木筏上,然后再从剩下的那些山羊身上再放最重的山羊,这对木筏的容量来说不会太重,然后再放下一只,依此类推,直到没有了。由于其能力,更多的山羊可以上筏。在那之后,他将它们带到另一岸(进行一次训练),然后返回以使更多的山羊登上木筏并进行另一次训练。 (木筏的承载力必须至少等于最重的山羊的体重)
因此,我需要编写一个脚本,计算给定数量的课程 K ,山羊的数量 N 和它们的重量( A1,A2 等)。由于它是一个相对较小的常数,因此忽略了乔治的体重 (无需将其添加到计算中)。
到目前为止,所有记录都是根据挑战的要求进行的。
适当解决方案的结果示例:
6只山羊,2道菜
每只山羊的体重:26、7、10、30、5、4
结果(木筏的最小容纳量):42
这些课程是:(30,10); (26,7,5,4)
以下解决方案不遵循规则:(30,7,4); (26,10,5)-因为体重为10公斤的山羊可以在第一道比赛中,并且必须遵守规则。
我的解决方案尝试:
import itertools
goatnum = 0
courses = 0
goatw = []
counter = 0
goatnum = int(input("Enter the number of goats: "))
courses = int(input("Enter the number of courses: "))
for g in range(goatnum):
goatw.append(int(input("Enter the weight of goat #{}: ".format(g+1))))
goatw = sorted(goatw, reverse=True)
goats = sum(goatw)
result = []
permlen = len(goatw)/courses
while not result:
result = [seq for i in range(len(goatw), 0, -1) for seq in itertools.permutations(goatw, permlen) if sum(seq) == int(goats/courses)]
if not result:
goats += 1
permlen += 1
else:
break
print(result)
我正在使用置换来完成任务,仅仅是因为我不知道另一种处理方式。目前,从结果中,我只能得到不遵守规则的解决方案(对于给定的示例)。我在内部找到了解决方案(30, 7, 4); (26, 10, 5)
,但是,如果某课程的山羊数量少于3,则什至没有结果,所有课程的山羊数均为3。
给定示例的输出(6头山羊,2道菜,w:26,7,10,30,5,4):
[(30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30), (30, 7, 4), (30, 4, 7), (26, 10, 5), (26, 5, 10), (10, 26, 5), (10, 5, 26), (7, 30, 4), (7, 4, 30), (5, 26, 10), (5, 10, 26), (4, 30, 7), (4, 7, 30)]
我对这种事情是陌生的,我也从互联网上获得了使用排列的例子。我的代码哪里错了?我知道我可以做一个函数来检查我是否遵守规则的结果,如果不能,请修复结果,但是我不知道该怎么做。任何帮助将不胜感激。
答案 0 :(得分:0)
我相信您遇到的问题是,您生成的所有排列都由3只山羊组成。如果要生成 N 个山羊的所有可能排列,然后将这些排列切成 K 个位置,则正确的解决方案就是这些列表之一。例如,使用3只山羊A
,B
和C
,我们得到以下排列:
(A,B,C), (A,C,B), (B,A,C), (B,C,A), (C,B,A), (C,A,B)
假设我们有2门课程。现在,假设我们有 K -1个棒(在这种情况下为1个),我们可以将它们放置在 N 中-在每个排列中都放置1个位置(在本例中为2个)。可以在任何山羊之间或边缘放置一根棍子。摇杆用作分隔符,决定每次旅行要去的山羊组。在一般情况下,您要放置 K-1 个木棍,并且您不想在同一位置放置两个木棍,因为那将意味着您将有一次旅行,而船上没有山羊。然后我们得到以下空间,可以在其中搜索解决方案:
(A | B C), (A B | C)
(A | C B), (A C | B)
(B | A C), (B A | C)
(B | C A), (B C | A)
(C | B A), (C B | A)
(C | A B), (C A | B)
请注意,您也可以在最左侧“放置操纵杆”,这意味着将有一次空行程,所有山羊都经过一次行程,但是显然这里找不到最佳解决方案,因为它将总是更好利用尽可能多的行程。请注意,由于需要按顺序装载山羊,因此许多可能性都不符合规则,因此需要对这些结果进行过滤,以删除不遵守规则的结果。
从这里开始,只需找出这些可能性中的哪一个需要最小容量的船,就可以通过计算每种可能性中的最大和并选择总和最小的可能性来计算。 >
因此,总而言之,使用置换解决此问题的一种方法是:
生成所有可能的山羊排列。
生成将每个排列细分为 K 个组的所有方式。
摆脱步骤2生成的任何不遵守规则的候选。
从其余候选人中找到最重旅程比其他候选人最重旅程的人。
这绝不是最佳解决方案,但应该可以完成工作。