我很难找到解决办法,但我不知道。
RobotA和RobotB选择N个数字的排列开始。 RobotA首先选择,他们交替选择。每转一圈,机器人只能从排列中挑选任何一个剩余的数字。当剩余数字形成递增序列时,游戏结束。选择最后一个回合的机器人(之后序列变得越来越大)赢得了游戏。
假设两者都发挥得最好,谁赢了?
示例1:
The original sequence is 1 7 3.
RobotA wins by picking 7, after which the sequence is increasing 1 3.
示例2:
The original sequence is 8 5 3 1 2.
RobotB wins by selecting the 2, preventing any increasing sequence.
有没有任何已知的算法可以解决这个问题?请给我任何关于在哪里看的提示或想法真的很感激!
答案 0 :(得分:4)
给定不同数字的序列w
,让N(w)
为w
的长度,让L(w)
为w
中增长最长的子序列的长度}。例如,如果
w = 3 5 8 1 4
然后N(w) = 5
和L(w) = 3
。
游戏在L(w) = N(w)
时结束,或等同于N(w) - L(w) = 0
。
向后游戏,如果在RobotX的转弯N(w) - L(w) = 1
,则最佳游戏是移除不在最长的子序列中的唯一字母,从而赢得游戏。
例如,如果w = 1 7 3
,则N(w) = 3
和L(w) = 2
具有最长的后续子序列为1 3
。删除7
会导致序列递增,确保删除7
的玩家获胜。
回到上一个示例w = 3 5 8 1 4
,如果删除了1
或4
,那么对于结果排列u
我们有N(u) - L(u) = 1
,因此,移除1
或4
的玩家肯定会输给有能力的对手。然而,任何其他比赛都会导致胜利,因为它迫使下一名球员进入失败位置。在这里,最佳游戏是移除3
,5
或8
中的任何一个,之后N(u) - L(u) = 2
,但在下一次移动N(v) - L(v) = 1
之后。
沿着这些方向的进一步分析应该为任何一个球员带来最佳策略。
我所知道的最近的数学游戏是单调序列游戏。在单调序列游戏中,两个玩家交替地从一些固定有序集合中选择序列的元素(例如1,2,...,N
)。当结果序列包含长度为A
的升序子序列或长度为D
的递减子序列时,游戏结束。这个游戏的起源是鄂尔多斯和Szekeres定理,在MONOTONIC SEQUENCE GAMES中可以找到一个很好的阐述,而Bruce Sagan的这个slide presentation也是一个很好的参考。
如果你想了解更多关于游戏理论的信息,或者特别是这些类型的游戏,那么我强烈推荐Berlekamp,Conway和Guy为你的数学游戏赢得方式。我认为,第3卷涉及这些类型的游戏。
答案 1 :(得分:3)
看起来像Minimax问题。
答案 2 :(得分:1)
我想这个任务有更快的解决方案。我会想。 但我可以给你一个O(N!* N ^ 2)复杂度的解决方案。
首先,请注意从N排列中选取数字等同于以下内容:
从N排列中选择号码。我们是X号。
使用规则重新分配号码:
1 = 1
2 = 2
...
X-1 = X-1
X =没什么,它消失了。
X + 1 = X
...
N = N - 1
你得到了N-1号码的排列。
示例:
1 5 6 4 2 3
选择2
1 5 6 4 3
重新分配
1 4 5 3 2
让我们使用这个作为移动,而不仅仅是选择。很容易看到游戏是等价的,玩家A在这个游戏中赢得一些排列,当且仅当它赢得了原始。
让我们给出N个数字,N-1个数字,...... 2个数字的所有排列代码。
定义F(x) - > {0; 1}(其中x是置换代码)是当前
时为1的函数玩家获胜,如果当前玩家失败则为0。容易看到F(1 2 .. K-1 K)= 0。
F(x)= 1如果至少在移动时将x转换为y,并且F(y)= 0。
F(x)= 0如果任何将x转换为y,F(y)= 1的移动。
所以你可以使用带有记忆的递归来计算:
Boolean F(X)
{
Let K be length of permutation with code X.
if you already compute F for argument X return previously calculated result;
if X == 1 2 .. K return 0;
Boolean result = 0;
for i = 1 to K do
{
Y code of permutation get from X by picking number on position i.
if (F(y) == 0)
{
result = 1;
break;
}
}
Store result as F(X);
return result;
}
对于每个参数,我们只计算一次这个函数。有1个!长度为1,2的排列!长度为2的排列.N!长度为N的排列。对于置换长度K,我们需要进行O(K)运算来计算。所以复杂性将是O(1 * 1!+ 2 * 2!+ .. N * N!)=< = O(N!* N ^ 2)= O(N!* N ^ 2)
答案 3 :(得分:0)
这是Wisdom的Wind算法的Python代码。它打印出RobotA的胜利。
import itertools
def moves(p):
if tuple(sorted(p)) == p:
return
for i in p:
yield tuple(j - (j > i) for j in p if j != i)
winning = set()
for n in range(6):
for p in itertools.permutations(range(n)):
if not winning.issuperset(moves(p)):
winning.add(p)
for p in sorted(winning, key=lambda q: (len(q), q)):
print(p)