如何优化python动态编程背包(多处理?)
我已经解决了,但它仍然太慢,无法被接受 我也尝试过让它使用多处理,但我失败了,因为它仍然比较慢。 即使使用如何优化python动态编程背包(多处理?),python,knapsack-problem,pypy,Python,Knapsack Problem,Pypy,我已经解决了,但它仍然太慢,无法被接受 我也尝试过让它使用多处理,但我失败了,因为它仍然比较慢。 即使使用pypy,基本实现也会在spoj上返回“超出时间限制”。 那么,我该如何改进它呢 多处理实现有什么问题 # -- shipyard from collections import defaultdict #W = 100 total weight #N = 2 number of types #value | weight #1 1 #30 50 # resu
pypy
,基本实现也会在spoj上返回“超出时间限制”。
那么,我该如何改进它呢
多处理实现有什么问题
# -- shipyard
from collections import defaultdict
#W = 100 total weight
#N = 2 number of types
#value | weight
#1 1
#30 50
# result -> 60 = minimum total value
#c = [1, 30]
#w = [1, 50]
def knap(W, N, c, w):
f = defaultdict(int)
g = defaultdict(bool)
g[0] = True
for i in xrange(N):
for j in xrange(W):
if g[j]:
g[j+w[i]] = True
#print "g("+str(j+w[i])+") = true"
if ( f[j+w[i]]==0 or f[j+w[i]]>f[j]+c[i]):
f[j+w[i]] = f[j]+c[i]
#print " f("+str(j+w[i])+") = ",f[j+w[i]]
if g[W]:
print f[W]
else:
print -1
def start():
while True:
num_test = int(raw_input())
for i in range(num_test):
totWeight = int(raw_input())
types = int(raw_input())
costs = defaultdict(int)
weights = defaultdict(int)
for t in range(int( types )):
costs[t], weights[t] = [int(i) for i in raw_input().split()]
knap(totWeight, types, costs, weights)
return
if __name__ == '__main__':
start()
这是多处理版本:
# -- shipyard
from multiprocessing import Process, Queue
from collections import defaultdict
from itertools import chain
W = 0
c = {} #[]
w = {} #[]
def knap(i, g, f, W, w, c, qG, qF):
for j in xrange( W ):
if g[j]:
g[j+w[i]] = True
#print "g("+str(j+w[i])+") = true"
if ( f[j+w[i]]==0 or f[j+w[i]]>f[j]+c[i]):
f[j+w[i]] = f[j]+c[i]
#print " f("+str(j+w[i])+") = ",f[j+w[i]]
qG.put( g)
qF.put( f)
def start():
global f, g, c, w, W
while True:
num_test = int(raw_input())
for _ in range(num_test):
qG = Queue()
qF = Queue()
W = int(raw_input())
N = int(raw_input()) # types
c = {} #[0 for i in range(N)]
w = {} #[0 for i in range(N)]
f = defaultdict(int)
g = defaultdict(bool)
g[0] = True
for t in range( N ):
c[t], w[t] = [int(i) for i in raw_input().split()]
# let's go parallel
for i in xrange(0, N, 2):
k1 = Process(target=knap, args=(i, g, f, W, w, c, qG, qF))
k2 = Process(target=knap, args=(i+1, g, f, W, w, c, qG, qF))
k1.start()
k2.start()
k1.join()
k2.join()
#while k1.is_alive(): # or k2.is_alive():
# None
#g2 = defaultdict(bool, chain( g.iteritems(), qG.get().iteritems(), qG.get().iteritems()))
#f2 = defaultdict(int, chain( f.iteritems(), qF.get().iteritems(), qF.get().iteritems()))
g2 = defaultdict(bool, g.items()+ qG.get().items()+ qG.get().items())
f2 = defaultdict(int, f.items()+ qF.get().items()+ qF.get().items())
g = g2
f = f2
print "\n g: ", len(g), "\n f: ", len(f),"\n"
if g[W]:
print f[W]
else:
print -1
return
if __name__ == '__main__':
start()
我可能还不知道如何使两个进程在同一个字典上高效地工作许多使用Python的人在编程竞赛网站上面临同样的问题。我发现,对于那些需要在大数据结构上构造和迭代的接受大输入的问题,最好是完全抛弃Python。在C或C++中简单地重新实现相同的解决方案。众所周知,Python的速度比经过优化的C/C++代码慢10到100倍
您的代码看起来不错,但要获得更快的速度,您所能做的实在太少了(除了大的O改进或经历诸如多处理之类的困难)。如果必须使用Python,请尽量避免创建不必要的大列表,并使用您能想到的最有效的算法。在提交解决方案之前,您还可以尝试生成并运行大型测试用例。一些编程竞赛将明确禁止多线程或阻止多线程,因此请尝试到其他地方查看。在那些时候,我的方法是使用分析工具来查看代码在哪里挣扎。您可以尝试内置的cProfile(
python-mcprofile-o
),然后使用这个出色的可视化工具:
一旦你有了你的视觉化环顾四周,就去挖掘盒子。有些时候,有些事情不是直接显而易见的,但一旦检查了运行时间就有意义了。i、 一个常见的问题(不确定是否是您的情况)是检查列表成员资格。在这种情况下,使用集合要快得多,如果您以后需要订单,通常需要保留一个单独的列表和集合。关于将变量导入局部空间等,还有很多提示。您可以在此处查看列表:这肯定是最佳选项,但并不总是一个选项。总有一个中间步骤,您可以将程序的某些部分编码为C/C++扩展模块。请看这里:如果速度在某些方面是我关心的问题,我肯定会在商业项目中实现C扩展模块,但这对于一个竞赛问题来说确实是值得的?你必须使用
defaultdict
?由于列表的范围是预先知道的,因此最好使用[None]*int(types)
初始化数组。