这一题用递归很简单,直接深度优先搜索所有排序,取最大值即可,但是完全没有DP的思想而且求解时间不可接受;但是如果要DP,如何减少状态数?要知道本题的输入数列排序是影响最终结果的。
下面的解法是DP的,这个DP的妙处在于仍然用输入数列A的子数列组合As作为状态,但是这个状态下面仍然分一些子状态,不过不是用这个子数组的所有排序作为子状态而是用一种hash的方式,即将该子数组的可能结果(子数组每一种排序按题目算法所求得的状态值R=x+x^As[i])对64(2的6次方)求余所得作为子状态的index。
为什么可以这么做?因为题目中数组A最大的数为50(6bit,可覆盖),所以在一个状态转移到下一状态时,即某个子数组新加入一个元素的时候,其实只需要考虑状态值R的低6位不同的情况即可,因为只有低6位有后效性,只有低6位相同的所有排序只需取最大状态值(这里不用求具体排序,主要求最大值),其他都不用考虑了,而不同的低6位值可能带来不同的有效子状态。说白了,就是当前低6位不一样的,现在不能判定以后谁优谁劣,而当前低6位相同的,已经可以毫无顾忌的进行优胜劣汰了。这样一来就大大减少了需要考虑的分支,于是求解效率就呈几何级数地提高了。
class Xscoregame:
def getscore(self, a):
s = {(0,0):0}
n = len(a)
ln = 1<<n
for i in range(0, ln):
for j in range(0, 64):
if s.get((i,j), -1) < 0:
continue
for idx,k in enumerate(a):
e = 1 << idx
if e & i > 0:
continue
t = s[(i,j)]
t += t ^ k
ni = i|e
nj = t%64
s[(ni, nj)] = max(s.get((ni, nj),-1), t)
ret = 0
nn = ln - 1
for j in range(0, 64):
ret = max(ret, s.get((nn,j),-1))
return ret
if __name__ == "__main__":
print Xscoregame().getscore([1,2,3])
print Xscoregame().getscore([10,0,0,0])
print Xscoregame().getscore([1,1,1,1,1,1])
print Xscoregame().getscore([1,0,1,0,1,0,1,0])
print Xscoregame().getscore([50,0,1,0,1,0,1,0,1,0,1,0,1,0,1])