Algorithm “的算法”;“拿起数字游戏”;

Algorithm “的算法”;“拿起数字游戏”;,algorithm,permutation,puzzle,Algorithm,Permutation,Puzzle,我正在努力寻找解决方案,但我对此一无所知 RobotA和RobotB选择N个数字的排列作为开始。罗博塔先选,他们轮流选。每个回合,机器人只能从排列中选择剩余的任何一个数字。当剩余的数字形成递增序列时,游戏结束。选择最后一个回合的机器人(之后序列增加)赢得游戏 假设双方都发挥最佳状态,谁会赢 示例1: 示例2: 有没有已知的算法可以解决这个问题?请给我任何建议或想法,在哪里看将是真正的感谢 看起来是个问题 我想这项任务有更快的解决方案。我会想。 但我可以给你一个O(N!*N^2)复杂度的解决方案

我正在努力寻找解决方案,但我对此一无所知

RobotA和RobotB选择N个数字的排列作为开始。罗博塔先选,他们轮流选。每个回合,机器人只能从排列中选择剩余的任何一个数字。当剩余的数字形成递增序列时,游戏结束。选择最后一个回合的机器人(之后序列增加)赢得游戏

假设双方都发挥最佳状态,谁会赢

示例1:

示例2:


有没有已知的算法可以解决这个问题?请给我任何建议或想法,在哪里看将是真正的感谢

看起来是个问题

我想这项任务有更快的解决方案。我会想。 但我可以给你一个O(N!*N^2)复杂度的解决方案

首先,请注意,从N置换中选取的编号等效于以下内容:

  • 从N-置换中选取数字。让我们看看它是X号

  • 使用规则重新分配号码:

  • 1=1

    2=2

    X-1=X-1

    没什么,它不见了

    X+1=X

    N=N-1

    得到N-1个数的排列

    例如:

    156423

    选择2

    1 5 6 4 3

    重新分配

    1 4 5 3 2

    让我们用这个作为移动,而不是拾取。也很容易看出游戏是等价的,玩家A在这个游戏中赢得一些排列,当且仅当它在原版中获胜

    让我们给N个数的所有排列,N-1个数。。。2个数字

    定义F(x)->{0;1}(其中x是置换码)是当前值为1的函数

    玩家获胜,如果当前玩家失败,则为0。很容易看到F(12..K-1k)=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,2的排列!长度为2.的排列。。N长度为N的置换。对于置换长度K,我们需要进行O(K)运算来计算。因此复杂性将是O(1*1!+2*2!+…N*N!)=给定一个不同数字的序列
    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
    的下降子序列时,游戏结束。这个游戏起源于鄂尔多斯和塞克勒斯的一个定理,其中有一个很好的解释,布鲁斯·萨根的这篇文章也是一个很好的参考


    如果你想更多地了解一般的博弈论,或者这类游戏,那么我强烈推荐Berlekamp、Conway和Guy为你的数学游戏设计的获胜方式。我相信,第三卷是针对这类游戏的。

    这里是智慧之风算法的Python代码。它打印出罗博塔的胜利

    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)
    

    很抱歉没有真正的解决方案,但我发现如果你保持英语基础,更多的人会理解。把英语作为第二语言,我也觉得有必要使用像“排列”这样的大词,但简单地说“重新排列”会使你更容易阅读和理解你要找的东西。谢谢你的建议。@user85569我不同意。没有理由使语言哑口无言。尤其是当置换是数学和计算机科学中的一个常用词时。@user85569,置换是一个标准的数学术语。它不能用重新安排来代替。@Yuriy Faktorovich我没有用英语教数学或计算机科学。所以我不得不在谷歌上查这个词,知道他想说什么。它阻碍了这一过程,因为我相信很多人都不是以英语为第一语言,也不是用英语教学的。是一个让每个人都更容易理解的建议。。。因为这是互联网…我不认为这是正确的方式。这将是非常缓慢和非常难以实现的,因此游戏是最佳的。@IVlad你有更好的建议吗?Minimax或alpha-beta修剪是探索的标准方法
    w = 3 5 8 1 4
    
    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)