我在SPOJ Problem 423: Assignments上遇到问题。在
她给每个学生布置的作业都是唯一的,这样他就可以计算出每个问题的唯一数量。我想出了一种方法来将输入解析为一个名为preferences
的列表列表。一个包含0和1的内部主题列表是一个整数。在
例如输入:
1 1 1
1 1 1
1 1 1
我得到[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
。在
对于输入:
^{pr2}$我得到了列表[[0, 3, 9, 10], [0, 1, 2, 3, 4, 6, 8], [0, 3, 6, 7, 9], [0, 2, 3, 4, 6, 7, 9, 10], [1, 2, 3, 5, 8, 9, 10], [0, 1, 2, 5], [4, 6, 10], [0, 2, 3, 10], [2, 4, 5, 9, 10], [0, 1, 2, 6, 8, 10], [0, 4, 5, 6, 7]]
。在
现在我需要做的是计算从每个内部列表中选择一个唯一数字的方法的数量,这样就不会选择两次元素,并且0到n-1(包括0和n-1)之间的每个数字在所有选择中只选择一次。对于第一个示例输入,这是微不足道的,它是3! = 6
。但是在第二个例子中,我很难找到一种方法来计算有效选择的数量。对于第二个输入,他们给出的答案是7588,但我不知道如何得到这个答案。在
我已经尝试过使用蛮力方法来查找[0,…,n-1]的所有排列,并试图根据集合成员关系来判断它们是否是有效的组合,但它太慢了,当我试图迭代11! = 39916800
排列时,它确实使我的计算机崩溃。所以我需要做的是找到一个更有效的方法来计算这个。在
这是我目前为止的代码。它目前所做的就是将来自stdin的输入解析成一个名为preferences的列表,并将其打印到stdout。在
def main():
t = int(raw_input())
from itertools import repeat
for _ in repeat(None, t):
n = int(raw_input())
preferences = [[] for _ in repeat(None, n)]
for student in xrange(n):
row = map(int, raw_input().split())
for i in xrange(len(row)):
if row[i] == 1:
preferences[student].append(i)
print preferences
if __name__ == '__main__':
main()
有什么方法可以让我有效地计算这个数吗?欢迎任何提示/提示。我不指望有人帮我解决这个问题。我只是不知道该如何处理这件事。在
我看到我在2005年解决了这个问题——它仍然是世界上第十快的,但是它使用的内存比其他公认的解决方案要少得多。看看今天的代码,我不知道它在做什么-哈哈;-)
如果我没记错的话,这是一个“禁止位置排列”的例子。这是一个可以和“rook多项式”一起使用的搜索词。它可以归结为计算0-1矩阵的“永久”(另一个搜索项),这是一项计算开销很大的任务。这就是为什么在SPOJ上找不到可接受的Python解决方案(我用C编写了我的解决方案)。在
因此,没有答案,但是有很多事情需要研究;-)为这个项目获得一个被接受的程序更多的是学习数学而不是聪明的编程。在
一个提示:在我的笔记中,我看到我通过特殊的大小写输入矩阵(包含所有的1)保存了一批运行时的批。在这种情况下,结果只是N的阶乘(对于N乘N的输入)。祝你好运:-)
扰流板警报!在
这显示了一种相对简单的实现0-1矩阵的Ryser公式的方法。行被视为普通整数,索引子集也被视为普通整数。可以添加许多微优化(例如,如果
prod
变为0,则提前脱离循环;如果矩阵完全为1,则返回math.factorial(n)
;等等)。在下面是一个简单的实现(使用第二个示例矩阵):
问题是计算图中最大二部匹配的总数。在
以下摘录自Wikipedia article可能会有所帮助
相关问题 更多 >
编程相关推荐