遗传算法-N皇后问题-对角线冲突

时间:2019-04-06 18:46:34

标签: java genetic-algorithm n-queens

我正在研究基于遗传算法的Java代码。我想解决N皇后问题,需要计算对角线上的冲突/冲突。我无法正确找到对角线中的碰撞。

我找到了一种算法,但是无法正确理解它如何在我的代码中实现。 我生成一个8x8的二维数组

char Queens[][]={
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},
                    {'.','.','.','.','.','.','.','.'},

            };

我已经找到列和行的冲突。只需计算对角线冲突即可。

 for(int i=0;i<8;i++){
            Queens[myarr[i]][i] = 'q';
        }

int conflict=0;
        for (int i=0;i<8;i++){
            for (int j=0;j<8;j++){
                if(Queens[i][j]=='q'){




                    for(int left=j-1;left>=0;left--){
//                        System.out.print(left+"      "+j);
                        if(Queens[i][left]=='q'){
                            conflict++;
                        }
                    }


                        for(int right=j+1;right<8;right++)
                        {
                               if(Queens[i][right]=='q'){
                                conflict++;
                            }
                        }

这是我找到的算法,但无法在我的Queens[][]阵列上实现

# calculate diagonal clashes
for i in range(len(chromosome)):
    for j in range(len(chromosome)):
        if ( i != j):
            dx = abs(i-j)
            dy = abs(chromosome[i] - chromosome[j])
            if(dx == dy):
                clashes += 1


return 28 - clashes

1 个答案:

答案 0 :(得分:2)

您的代码存在一些问题:

  • 代码对冲突进行两次计数。没必要,因为如果q1q2之间存在冲突,则对称原因也会在q2q1之间发生冲突。 。因此,原则上只在一个方向上向左或向右计数就足够了。以编程方式,这意味着仅应使用两个内部循环之一(带有right计数器的循环或带有left计数器的循环)。

    因此,第一个更改应该是删除一个内部循环。出于性能原因,这也是有道理的。

  • 第二个问题是,目前仅计算相同行中的冲突,而没有计算相同列中的冲突。

    因此,第二个更改应该是考虑同一列中的冲突。从编程上讲,它类似于先前的情况,但是现在您必须考虑类别 top和bottom 而不是 left和right

  • 接下来的问题涉及对角线上的冲突的考虑(这是原始问题)。

    您有关对角线冲突的伪代码可能来自here。在这种方法中,候选溶液被视为具有n基因的染色体。每个基因对应于nxn棋盘的一行,并指示皇后在该行中的位置。即候选解决方案对应于大小为n的数组,其中每个元素都包含女王/王后在属于相应元素的行中的位置。

    相比之下,您的代码使用nxn矩阵直接表示棋盘。这意味着解决方案候选者对应于一个nxn矩阵,其中每个与带有皇后的字段相对应的元素都包含字符q

    我看不到如何将伪代码与您的方法结合起来。这就是为什么我建议以下与您的方法兼容的替代方法:

    对角线分为两类:

    • 一个类别包括从左上到右下的对角线。这种情况可以按以下方式处理:

      for (int bottom = i + 1, right = j + 1; bottom < 8 && right < 8; bottom++, right++) {
          if (Queens[bottom][right] == 'q') {
              conflict++;
          }
      }
      
    • 其他类别包括从右上到左下的对角线。从编程上来说,这类似于先前的情况 因此可以类似的方式实现。

进行所有更改后,总共有四个内部循环。第一个考虑了行内的冲突,第二个考虑了列内的冲突,以及对角线内的第三个和第四个冲突。使用以下矩阵进行测试...

{ 'q', '.', '.', '.', '.', '.', '.', 'q' }, 
{ '.', '.', '.', '.', '.', '.', '.', '.' },
{ '.', '.', 'q', '.', '.', 'q', '.', '.' }, 
{ '.', '.', '.', '.', '.', '.', '.', '.' },
{ '.', '.', '.', '.', '.', '.', '.', '.' }, 
{ '.', '.', 'q', '.', '.', 'q', '.', '.' },
{ '.', '.', '.', '.', '.', '.', '.', '.' }, 
{ 'q', '.', '.', '.', '.', '.', '.', 'q' },

...应导致20个冲突(2个对角线各6个= 3 + 2 + 1个冲突,4行各1个冲突和4列各1个冲突:2 * 6 + 4 * 1 + 4 * 1 = 20)。