这是游戏:
有一个0和1的字符串,每回合允许玩家进入 将一组连续的1转换为0。玩家最多可以兑换k 连续的1到0并且必须在他的中将至少一个1转换为0 移动。无法移动的玩家输了。
示例:
10100111(k = 2)
此处获胜的举动将是:10100101(将第二个1转换为0)
这是一款2人制的公正游戏,我试图将其分析为nim游戏的变体。每个堆都有n个堆,带有 i 大理石( n 连续的1组)。玩家可以通过从该堆中的任何位置移除最多k个大理石来将堆分成2堆。假设一个堆有5个大理石(*****
),你通过从位置2(* **
)移除k = 2大理石来拆分堆。此外,如果您要删除第一个或最后一个k弹珠,堆将不会拆分,只有它的大小会减少k。
这个模型可以帮助找到原始游戏的策略吗?如果是,那么最佳策略是什么?
任何帮助将不胜感激!
答案 0 :(得分:0)
正如ypercube所说,游戏可以被解决,并且每个位置都可以显示它是赢(N位)还是失去(P)位置。
这足以考虑:
初始失败(P)位置是n
零的字符串,
获胜(N)位置是从哪里移动到某个P位置的任何位置,
P位置是每次移动都会导致N位置的位置。
通过从初始位置开始,很容易找到每个位置的值,找到下一个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()
足以实现类似游戏的解算器。