【问题标题】:factorial array for tic tac toe井字游戏的阶乘数组
【发布时间】:2012-03-09 04:05:40
【问题描述】:

我目前正在尝试自学 C++ 和一般编程。因此,作为一个初学者项目,我正在制作一种遗传算法,为井字游戏创建最佳 AI。我没有参加任何编程课程,所以这不是家庭作业。我只是对人工智能很感兴趣。

所以我试图创建一个阶乘的多维数组,在我的例子中是 9! .例如,如果你做了 3 个中的一个!它将是 array[3][6] = { {1, 2, 3}, {1, 3, 2}, {2, 3, 1}, {2, 1, 3}, {3, 2, 1 }, {3, 1, 2}}。基本3!或 3*2*1 将是您可以按顺序排列 3 个数字的方式数量。

我认为解决方案应该很简单,但我一直在试图找出如何提出一个简单的解决方案。我试图交换它们,试图将它们向右移动,递增等.. 有效的方法是显而易见的,我不知道如何编写它们。

所以,如果您知道如何解决它,那就太好了。如果能给出一个编码格式就更好了。任何帮助表示赞赏。

我也在用 C++ 编写代码。

【问题讨论】:

    标签: c++ logic


    【解决方案1】:

    可以使用 STL 的 next_permutation 函数

    http://www.cplusplus.com/reference/algorithm/next_permutation/

    【讨论】:

    • 谢谢,这就是我一直在寻找的东西,我会检查一下,看看我是否能确切地知道该功能是如何做到的。
    【解决方案2】:

    我实际上曾经为此手动编写过一个算法。这里是:

    bool incr(int z[NUM_INDICES]){
        int a=NUM_INDICES-1;
        for(int i=NUM_INDICES-2;i>=0;i--)
          if(z[i]>z[i+1]) a--;
          else break;
        if(a==0) return false;
        int b=2147483647,c;
        for(int i=a;i<=NUM_INDICES-1;i++)
          if(z[i]>z[a-1]&&z[i]-z[a-1]<b){
            b=z[i]-z[a-1];
            c=i;
          }
        int temp=z[a-1]; z[a-1]=z[c]; z[c]=temp;
        qsort(z+a,NUM_INDICES-a,sizeof(int),comp);
        return true;
    }
    

    这是增量函数(即,您有一个类似 [3,2,4,1] 的数组,将其传递给 this,然后它会将其修改为 [3,4,1,2])。它解决了这样一个事实,即如果数组的最后一个 d 元素按降序排列,那么下一个数组(按“字母”顺序)应该满足以下条件:1)最后一个 d+1 个元素之间是一个排列; 2) 倒数第 d+1 个元素是最后一个 d+1 个元素中的下一个最高元素; 3) 最后的 d 元素应该按升序排列。当你有类似 [2,5,3, 8,7,6,4,1] 的东西时,你可以直观地看到这一点: d = 5 在这种情况下; 3 变成最后 d+1 = 6 个元素的下一个最高值;而最后的d = 5按升序排列,所以变成了[2,5,4,1,3,6,7,8]。

    第一个循环基本确定d。它向后循环数组,比较连续的元素,以确定最后按降序排列的元素的数量。在循环结束时,a 成为降序排列的第一个元素。如果a==0,那么整个数组是降序排列的,不能再做任何事情了。

    下一个循环确定第 d+1 个倒数第二个元素应该是什么。我们指定它应该是最后一个 d+1 元素中的下一个最高元素,所以这个循环确定它是什么。 (注意 z[a-1] 是第 d+1 个倒数第二个元素。)在循环结束时,b 包含最低的 z[i]-z[a-1],即为正数;也就是说,z[i] 应该大于z[a-1],但尽可能低(这样z[a-1] 就成为下一个最高元素)。 c 包含对应元素的索引。我们丢弃了b,因为我们只需要索引。

    接下来的三行交换z[a-1]z[c],因此第 d+1-th-to-last 元素获取行中的下一个元素,而另一个元素 (@987654333 @) 保留z[a-1]。最后,我们使用qsort 对最后的d 元素进行排序(comp 必须在别处声明;参见qsort 上的C++ 文档)。

    【讨论】:

    • 这很好,谢谢,所以第一部分按顺序遍历它们,当它们不按降序时中断。然后,如果它的唯一长度为 0,则返回 0。我猜 2147483647 只是一个随机数。我还没有弄清楚是什么变量保存了排列的值,但我稍后会看更多。
    • 2147483647 是最高可能的有符号整数 (2^31 - 1)。我们通过将b 与每个数组元素进行比较来使b 尽可能小,如果b 更高,则将其替换为数组元素。因此,我们为b 选择可能的最高值开始,以便它始终被替换。
    • 我实际上还没有创建排列。同样,这只是一个增量函数。您需要在 main 中创建一个数组来存储最终值和另一个数组来存储当前排列,然后使用循环将后者复制到前者,调用 incr(),并在返回 false 时退出.
    • 好,很酷,只是想知道您自己花了多长时间才想出这个?
    • 大概 30 分钟到一个小时
    【解决方案3】:

    如果你想要一个手工制作的函数来生成所有排列,你可以使用

    #include <cstdio>
    #define REP(i,n) FOR(i,0,n)
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define GI ({int t;scanf("%d",&t);t;})
    
    int a[22], n;
    
    void swap(int & a, int & b) {
        int t = a; a = b; b = t;
    }
    
    void perm(int pos) {
        if(pos==n) {
            REP(i,n) printf("%d ",a[i]); printf("\n");
            return;
        }
        FOR(i,pos,n) {
            swap(a[i],a[pos]);
            perm(pos+1);
            swap(a[pos],a[i]);
        }
        return;
    }
    
    int main (int argc, char const* argv[]) {
    
        n = GI;
        REP(i,n) a[i] = GI;
        perm(0);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-12
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多