正如 ypercube 所提到的,游戏可以解决,并且对于每个位置,都可以显示它是获胜(N 位置)还是失败(P)位置。
考虑一下就够了:
这样很容易找到每个位置的值,从初始位置开始,找到下一个 N 位置,从这些 N 位置找到(可能的)P 位置,...
这是解决这个游戏的python代码:
from itertools import product
from collections import defaultdict
class Game(object):
def __init__(self, n, k):
self.n, self.k = n, k
def states(self): # All strings with 0|1 of length n
return (''.join(x) for x in product(('0', '1'), repeat=self.n))
def set_zeros(self, c, i, l): # Set zeros in c from position i with length l
return c[:i] + '0'*l + c[i+l:]
def next_positions(self, c): # All moves from given position
for i in xrange(self.n):
if c[i] == '1': # First '1'
yield self.set_zeros(c, i, 1)
for j in xrange(1, self.k):
if i+j < self.n and c[i+j] == '1':
yield self.set_zeros(c, i, j+1)
else:
break
def lost_positions(self): # Initial lost position(s)
return ['0'*self.n]
def solve(self):
next_pos = {} # Maps position to posible positions after a move
prev_pos = defaultdict(set) # Maps position to posible positions before that move
win_lose = {} # True - win/N-position, False - lose/P-position, None - not decided
for s in self.states():
win_lose[s] = None
next_pos[s] = set(self.next_positions(s))
for n in next_pos[s]:
prev_pos[n].add(s)
# Initial loses positions
loses_to_check = set(self.lost_positions())
for c in loses_to_check:
win_lose[c] = False
#
while loses_to_check:
lost_c = loses_to_check.pop()
for w_pos in prev_pos[lost_c]: # Winning moves
if win_lose[w_pos] is None:
win_lose[w_pos] = True
for x in prev_pos[w_pos]: # Check positions before w_pos for P-position
if all(win_lose[i] for i in next_pos[x]):
win_lose[x] = False
loses_to_check.add(x)
return win_lose
comb = '10100111'
g = Game(len(comb), 2)
win_lose = g.solve()
print comb, win_lose[comb]
注意:更改/覆盖方法states()、next_positions(c)、lost_positions() 足以实现类似游戏的求解器。