当前位置: 首页 > 知识库问答 >
问题:

用回溯方法解决Nqueens问题,并将其作为CSP的最大约束值

拓拔野
2023-03-14

所以我现在正在做一个项目,把N个皇后放在NxN板上,防止它们互相攻击。这个项目是一个入门级的人工智能课程。它有几个特定的标准来获得满分,即在5秒或更短的时间内为任何板大小找到最多3个解决方案,最多为N=100。我目前正试图通过选择最受约束的行来使其成为约束满足问题,如果我正确理解,这将防止更接近完全受攻击的行到达该问题。

最初,用户将输入一个列号,一个皇后将放在该列的第一行。从那里,攻击板将通过增加所有对角线和行和列的值来使用行和列的组合来更新,下面是前者和后者的一个小示例

        void main()
    {
        int size, row, col;
        row = 1;
        cout << "Enter the board size: ";
        cin >> size;
        cout << "Enter column of first queen: ";
        cin >> col;

        cols[row] = col; // cols store the column value of each queen in that particular row.
        updateAttack(row, col, +1, size);
        findNextQueen(size);

        // return here if we found all the solution
        //cout << solutionCount << " solutions found. see NQueen.out.\n";
        cout << solutionCount << " solutions found. see NQueen.out.\n";
        fout.close();
        system("pause");
    }
void updateAttack(int r, int c, int change, int size)       // Updates the attack board given the location a queen being placed
{
    int r1, c1;

    // update diagnals
    for (r1 = r - 1, c1 = c - 1; r1 >= 1 && c1 >= 1; r1--, c1--)
        attack[r1][c1] += change;

    for (r1 = r + 1, c1 = c + 1; r1 <= size && c1 <= size; r1++, c1++)
        attack[r1][c1] += change;

    for (r1 = r - 1, c1 = c + 1; r1 >= 1 && c1 <= size; r1--, c1++)
        attack[r1][c1] += change;

    for (r1 = r + 1, c1 = c - 1; r1 <= size && c1 >= 1; r1++, c1--)
        attack[r1][c1] += change;

    // update columns 
    for (r1 = 1, c1 = c; r1 <= size; r1++) // k goes to each row          
        attack[r1][c1] += change;
}

这个节目的主要问题是选择把女王放在哪一排。在一个简单的回溯方法中,通过递归调用放置皇后,您可以向下增加行,并将皇后放置在当前没有受到攻击的行的第一个空格中,然后对下一行和下一个皇后执行相同的操作,直到无法放置皇后,在这种情况下,您可以回溯并试图通过将前一个皇后移动到下一个位置来修复它。下面的一个例子是用回溯和没有实现CSP来完成的。

    void findNextQueen(int r, int size)
{
      for (int c=1;c<=size;c++)
      {
        if (attack[r][c]==0) // not under attack
        {   
            cols[r]=c;  // assign another queen
            if (r<size)
            {
                updateAttack(r,c,+1, size);
                findNextQueen(r+1, size);
                updateAttack(r,c, -1, size);
            }
            else
            {
                print1solution(size);
                if (solutionCount >= 3)
                {
                    cout << solutionCount << " solutions found. see NQueen.out.\n";
                    system("pause");
                    exit(0);
                }
            }
        }
      }
    return;
}

约束满足试图解决回溯过程中引起的一个问题,在该问题中,稍后可能会用攻击值完全填充下面的行,这将导致需要大量的回溯,从而增加大量的回溯时间。它通过尝试首先选择有更多空间的行来进行攻击,以防止它们丢失,并要求后期回溯。我的例子,这是造成的问题,目前,它似乎总是来0解决方案可能在下面。

void findNextQueen(int size)
{
    int bestRowCount = 0;
    int bestRow = 2;

    for (int r = 2; r <= size; r++)         // Meant to find the most constrained row and use that as my r value for attack array
    {

            int aRowCount = 0;      // Count of attacks in current row
            for (int c = 1; c <= size; c++)
            {
                if (attack[r][c] >= 1)
                {
                    aRowCount++;
                }
            }
            if ((aRowCount > bestRowCount) && (aRowCount != size))
            {
                bestRowCount = aRowCount;
                bestRow = r;
            }
    }
    for (int c = 1; c <= size; c++)
    {
        if (attack[bestRow][c] == 0) // not under attack
        {
            cols[bestRow] = c;  // assign another queen
            if (queensLeft(size) == 1)  // returns true if there are rows that still lack a queen
            {
                updateAttack(bestRow, c, +1, size);
                findNextQueen(size);
                cols[bestRow] = 0;
                updateAttack(bestRow, c, -1, size);
            }
            else
            {
                print1solution(size);
                if (solutionCount >= 3)
                {
                    cout << solutionCount << " solutions found. see NQueen.out.\n";
                    system("pause");
                    exit(0);
                }
            }
        }
    }
    return;
}

共有1个答案

窦华晖
2023-03-14

LeetCode中也引入了非常类似的问题:

https://leetcode.com/problems/n-queens-ii

您可以转到讨论并找到带有代码解决方案的解释。您将需要修改代码,以便在达到限制时返回可能的结果。

 类似资料:
  • 本文向大家介绍C语言基于回溯算法解决八皇后问题的方法,包括了C语言基于回溯算法解决八皇后问题的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C语言基于回溯算法解决八皇后问题的方法。分享给大家供大家参考,具体如下: 问题描述: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例:在8X8格的国际象棋棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一

  • 本文向大家介绍C语言八皇后问题解决方法示例【暴力法与回溯法】,包括了C语言八皇后问题解决方法示例【暴力法与回溯法】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C语言八皇后问题解决方法。分享给大家供大家参考,具体如下: 1.概述: 八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后

  • 本文向大家介绍PHP回溯法解决0-1背包问题实例分析,包括了PHP回溯法解决0-1背包问题实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP回溯法解决0-1背包问题的方法。分享给大家供大家参考。具体分析如下: 这段代码是根据《软件设计师》教程的伪代码写的; 最麻烦的不是伪代码改成php,而是数组下标从0开始,及相应的下标判断问题; 带着调试输出一块写上 希望本文所述对大家的ph

  • 本文向大家介绍python 使用递归回溯完美解决八皇后的问题,包括了python 使用递归回溯完美解决八皇后的问题的使用技巧和注意事项,需要的朋友参考一下 八皇后问题描述:在一个8✖️8的棋盘上,任意摆放8个棋子,要求任意两个棋子不能在同一行,同一列,同一斜线上,问有多少种解法。 规则分析: 任意两个棋子不能在同一行比较好办,设置一个队列,队列里的每个元素代表一行,就能达到要求 任意两个棋子不能在

  • 本文向大家介绍Python使用回溯法子集树模板解决迷宫问题示例,包括了Python使用回溯法子集树模板解决迷宫问题示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python使用回溯法解决迷宫问题。分享给大家供大家参考,具体如下: 问题 给定一个迷宫,入口已知。问是否有路径从入口到出口,若有则输出一条这样的路径。注意移动可以从上、下、左、右、上左、上右、下左、下右八个方向进行。迷宫输入

  • 本文向大家介绍Mysql中文乱码问题的最佳解决方法,包括了Mysql中文乱码问题的最佳解决方法的使用技巧和注意事项,需要的朋友参考一下 一般来说,造成MySQL出现中文乱码的因素主要有下列几点: 1.server本身字符集设定的问题,例如还停留在latin1 2.table的语系设定问题(包含character与collation) 3.客户端程序(例如php)的连线语系设定问题 对此,强烈建议使