NQueen真的回溯了吗?

时间:2012-08-22 09:55:56

标签: algorithm data-structures backtracking n-queens

NQueen problembacktracking的一个着名例子。从source阅读后,我尝试了以下代码段。

int isSafe(int k,int i,int *x)
{
    int j;
    for(j=0;j<k;j++)
    {
              //old queen is placed at jth row of x[j] column
              //new queen to be placed at kth row of ith column
            if(i==x[j] || abs(k-j)==abs(i-x[j]))
                    return 0;
    }
    return 1;
}

int Nqueen(int k, int* sol, int N)
{
    int col;
    if( k == N )
    {
            printSol(sol,N);
            return 1;
    }
    else
    {
            for(col = 1;col <= N; col++)  //determines appropriate column number of the kth queen to be placed
            {
                    if( isSafe(k,col,sol) )
                    {
                            sol[k] = col;
                            if( Nqueen(k+1, sol, N) )
                                    return 1;
                            sol[k] = 0; // backtrack
                    }
            }
            return 0; // solution not possible
    }
}

我得到的是output

1 5 8 6 3 7 2 4 

然而,当我评论回溯的声明时,我得到了相同的output没有任何问题。

int Nqueen(int k, int* sol, int N)
{
    int col;
    if( k == N )
    {
            printSol(sol,N);
            return 1;
    }
    else
    {
            for(col = 1;col <= N; col++)  //determines appropriate column number of the kth queen to be placed
            {
                    if( isSafe(k,col,sol) )
                    {
                            sol[k] = col;
                            if( Nqueen(k+1, sol, N) )
                                    return 1;
                            // sol[k] = 0; <-------------- Notice this change
                    }
            }
            return 0;
    }
}

究竟是什么造成了NQueen问题,一个回溯问题?

这不是一个简单的递归方法吗?

3 个答案:

答案 0 :(得分:6)

sol[k] = 0不是回溯部分。回溯是在递归调用中完成的:if( Nqueen(k+1, sol, N) )

回溯的想法是一个详尽的搜索 - 你试图搜索所有可能性,直到找到一个。在这里,你正在尝试董事会中所有可能的女王任务,如果仍然安全的话,“继续”。如果您发现它不安全,则从失败的递归返回,并尝试下一个选项。

我相信注释掉的行只能确保如果找不到解决方案,结果数组是[0,...,0],而不是一些无意义的数组。

答案 1 :(得分:1)

回溯问题是一种编程范例,您可以尝试每种可能的组合。然后对于每个组合,检查到目前为止的组合是否正确。 以下是N(或8)女王问题的几个步骤。

  1. 从第0行开始,将第1位女王放在第0位。
  2. 现在将第二位女王放在第一排和第0位。
  3. 检查位置是否安全
  4. 如果不安全,请在第1行,第1行放置第2张女王。
  5. 不安全,现在将第2位女王放在第1行第2列。
  6. 通过将Queen放在每个可能的列上并检查它是否安全来进行此类操作。 您可以省略明显的错误条件,例如您不会将2个皇后放在同一行中。 下面是我的8皇后问题的代码,打印所有可能的解决方案。

    #include<stdio.h>
    
    
    int abs(int a){
            return a>0? a : -a;
    }
    
    int isSafe(int col[],int row){
            int row2,col2,i,yDiff,xDiff;
                    if(row == 0) return 1;
    
    
        for(row2=0;row2<row;row2++){
                        if(col[row2] == col[row])
                                return 0;
    
                        xDiff = col[row2] - col[row];
                        xDiff = abs(xDiff);
                        yDiff = row - row2;
                        if(xDiff == yDiff)
                                        return 0;
                }
    
        return 1;
    

    }

    int Nqueen(int col[],int n, int row){
            int i;
            if(row==n){
                    printf("\n");
                    for(i=0;i<n;i++)
                            printf("%d ",col[i]+1);
    
            }else{
                    for(i=0;i<n;i++){
                        col[row] = i;
                        if(isSafe(col,row)){
                                queen(col,n,row+1);
                        }
    
                }
        }
    

    }

    int main(){
            int col[8];
            queen(col,8,0);
    
    }
    

答案 2 :(得分:0)

首先,你真的需要理解算法(这会告诉你注释那些东西并不重要)。您已经注意到,此算法是递归的。它是回溯因为你

  • 将第k个女王设置为某个位置
  • 探索女王k + 1,k + 2,...
  • 的可能展示位置
  • 然后你回到第k个女王,把它放在别的地方,然后重复

参见步骤3,我们“回到”第k个女王。这就是我如何解释自己为何被称为回溯的原因。