C# N皇后算法。情节转折:女王也是一名骑士

C# N皇后算法。情节转折:女王也是一名骑士,c#,algorithm,recursion,C#,Algorithm,Recursion,试图在N*N板上修改骑士移动集的N皇后算法。在我的例子中,我在4*4和8*8板上测试它 我的算法,resp。我的递归无法处理骑士,因为它有时需要跳过一行。如果只是皇后的移动,则不需要跳过行,因为每行正好有1个Queen 问题出在我的Solve()函数中,因为我的递归与皇后数有关。通常情况下,每个板上的皇后数应为8。然而,加入骑士的移动会将数量减少到6。因此,我认为递归不够深入(只有6行深,而不是8行深) 例如,4*4板上的解决方案是(1,1)和(4,2)(行*列)。但它不能跳过第2行和第3行 如

试图在
N*N
板上修改骑士移动集的
N皇后
算法。在我的例子中,我在
4*4
8*8
板上测试它

我的算法,resp。我的递归无法处理骑士,因为它有时需要跳过一行。如果只是皇后的移动,则不需要跳过行,因为每行正好有
1个
Queen

问题出在我的
Solve()
函数中,因为我的递归与皇后数有关。通常情况下,每个板上的皇后数应为
8
。然而,加入骑士的移动会将数量减少到
6
。因此,我认为递归不够深入(只有6行深,而不是8行深)

例如,
4*4
板上的解决方案是
(1,1)
(4,2)
(行*列)。但它不能跳过第2行和第3行

如何使递归遍历所有行,同时能够跳过一些行

static int[]board=new int[9];
静态int cnt=0;
静态布尔CanPlace(int行,int列)//例如x[1]=2,第1行第2列有一个皇后
{            

对于(int j=1;j是的,这会变得更加困难。您需要对前面的问题进行一些修改,这使它成为一个有价值的编程练习

  • 记下你放了多少皇后
  • 允许跳过一行:不放置皇后不是失败;您只是不更新计数
  • 您需要保留到目前为止找到的最佳解决方案(最大数量的皇后),并继续运行,直到第一个皇后跑过中间点
  • 请注意,您不必在第一行中不允许有皇后。如果有一个解决方案在第一行中没有皇后,则有一个对应的解决方案,皇后数量相同,仅移动一行


    这足以让您继续前进吗?

    是的,这会变得更困难。您需要对前面的问题进行一些修改,这使得这是一个有价值的编程练习

  • 记下你放了多少皇后
  • 允许跳过一行:不放置皇后不是失败;您只是不更新计数
  • 您需要保留到目前为止找到的最佳解决方案(最大数量的皇后),并继续运行,直到第一个皇后跑过中间点
  • 请注意,您不必在第一行中不允许有皇后。如果有一个解决方案在第一行中没有皇后,则有一个对应的解决方案,皇后数量相同,仅移动一行


    这足以让你行动起来吗?

    我认为第一步是证明一个解决方案exists@Steve--当返回的计数为0时会发生这种情况。不过,这不是一种残酷的力量吗…原始n皇后的解决方案是greedy我们确实需要一个穷举搜索:贪婪算法不一定会产生一个最优解。有时,我们必须留下一个中间的空白行。我也注意到轻微的心理错误:永远不会有0的返回值。你总是可以放置至少一个皇后。我认为第一步是证明一个解决方案。exists@Steve--当返回的计数为0时会发生这种情况。但是,这不是一种残酷的力量吗?原始n皇后的解决方案是格里迪。我们确实需要一个彻底的西尔CH:贪婪算法不一定产生最佳的解决方案。有时候,我们必须在中间留一个空行。我也注意到轻微的心理错误:永远不会有0的返回值。你总是可以放置至少一个皇后。
        static int[] board = new int[9];
        static int cnt = 0;
    
        static bool CanPlace(int row, int col) // eg. x[1] = 2, 1st row 2nd col has a Queen
        {            
            for (int j = 1; j <= (row - 1); j++)
            {               
                if (board[j] == col || Math.Abs(board[j] - col) == Math.Abs(j - row)) return false;
                if ((Math.Abs(board[j] - col) - 1)  ==  Math.Abs(j - row)) return false;                
                //The line of code above should work for all of the possible moves of the Knight. 
                //At least it does for a 4x4 board, for the first two lines. 
                //Giving a pair of results = (1,1)(2,4) and the mirror (1,4)(2,1)
            }
            return true;
        }
    
        static void Solve(int row, int boardSize)
        {
            for (int col = 1; col <= boardSize; col++)
            {
                if (CanPlace(row, col)) //This only triggers 6 times per board
                {
                    board[row] = col;
                    if (row == boardSize - 2)   // Here i tried to fix it but the bottom rows get sacrificed               
                        PrintBoard();                   
                    else
                        Solve(row + 1, boardSize);                   
                }                    
            }        
        }
    
        static void PrintBoard()
        {
            Console.WriteLine();           
            cnt++;
            for (int i = 1; i <= board.Length-1; i++)
            {
                for (int j = 1; j <= board.Length - 1; j++)               
                    if (board[i] == j) Console.Write("Q");                   
                    else Console.Write(".");                    
                Console.WriteLine();
            }
    
            for (int i = 1; i <= board.Length - 1; i++)            
                Console.Write("{0},", board[i]);               
    
            Console.WriteLine();
        }
    
        static void Main(string[] args)
        {
            Solve(1, 8);
            Console.WriteLine("\nNumber of solutions: {0}\n",cnt);
        }