【问题标题】:8-Queens snippet8-Queens 片段
【发布时间】:2011-11-10 17:36:06
【问题描述】:

我目前正在学习回溯并陷入 8-queen 问题,我正在使用 8x8 矩阵,我认为我在将矩阵传递给函数方面遇到了一些问题,任何帮助都会非常感激。我不会不介意是否有人会对代码进行任何优化,谢谢。

这是我的代码。

#include <stdio.h>
#include <stdlib.h>

#define MAX 7



//void azzera(int **mat);
void posiziona(int **mat, int r,int c);
void stampa(int **mat);
int in_scacchi(int **mat,int r ,int c);

int main(int argc, char *argv[])
{



  int i=0,j=0;


  int **mat=(int **)malloc(sizeof(int *)*MAX);
  for(i=0;i<=MAX;i++){
      mat[i]=(int *)malloc(MAX*sizeof(int));               
      for(j=0;j<=MAX;j++){

           mat[i][j]=-1;
      }                        
   }


  printf("insert pos of the first queen on the first row (1-8) :");
  scanf("%d",&i);
  i-=1;
  mat[0][i]=1;

  posiziona(mat,1,0);
  stampa(mat); 

  system("PAUSE");  
  return 0;
}

/*void azzera(int **mat){

  int i=0,j=0;

  for(i=0;i<=MAX;i++){
      for(j=0;j<=MAX;j++){
           mat[i][j]=-1;
      }                        
   }

}*/

void stampa(int **mat){
     int i,j;

     for(i=0;i<=MAX;i++){
      for(j=0;j<=MAX;j++){
           printf(" %d",mat[i][j]);
      }
      printf("\n");                        
   }

}
void posiziona(int **mat, int r,int c){
    int i=0,riga=1,flag_col=-1,flag_riga=-1; 

    if(riga<=7&&flag_riga!=1){

         if(flag_riga==1){
             flag_riga=-1;                 
             posiziona(mat,r+1,0);
         }
         else if(in_scacchi(mat,r,c)==1){
                   if(c==MAX)
                       posiziona(mat,r-1,0);
                   posiziona(mat,r,c+1);  
         }
         else{
                   flag_riga=1;
         }
    }  
}

int in_scacchi(int **mat,int r ,int c){
    int i,j,k,m;
    int flag=0;   
   //col  
   for(i=0;i<r;i++){                 
      for(j=0;j<=c;j++){
           if(((mat[i][j]==1)&&(c==j))) 
                return 1;   

      }                          
   }
   //diag \
   for(i=0;i<MAX-r;i++){                 
      for(j=0;j<=MAX-c;j++){
           if(mat[MAX-r-i][MAX-c-j]==1) 
                return 1;   
      }                     
   }                          

   //antidiag 

   for(i=r+1;i<=MAX;i++){                 
      for(j=c+1;j<=MAX;j++){
           if(mat[r-i][c+j]==1) {
                return 1;   
           }                     
      }                          
   }
   return 0;

}

【问题讨论】:

  • 8 -Queens #define MAX 7 似乎不对。
  • 注意:8-Queens 问题可以在不将矩阵传递给递归函数的情况下解决
  • @user786653 - 呃,它确实考虑到计算机通常认为系列是从零开始的
  • 在 c 中 malloc 的类型转换是隐式的,明确地这样做是不受欢迎的。
  • @Brian Roach:没错,但malloc(MAX*sizeof(int)) 肯定不对。

标签: c algorithm recursion backtracking


【解决方案1】:

1. 一个明显的问题是内存分配:

  int **mat=(int **)malloc(sizeof(int *)*MAX);
  for(i=0;i<=MAX;i++){
      mat[i]=(int *)malloc(MAX*sizeof(int));   

鉴于 MAX 为 7,mallocs 为矩阵分配的内存太少(七个元素而不是八个元素)。

说实话,我会将 MAX 重命名为 SIZE 或类似名称,并将所有循环更改为使用严格小于,即

for(i = 0; i < SIZE; i++) {

我认为这稍微更惯用,更不容易出错。

2. 我没有尝试调试逻辑(我认为期望我们这样做是不公平的)。但是,我注意到除了main 之外,你没有分配给mat 的元素。对我来说,这表明代码不可能是正确的。

3. 除此之外,观察在有效解中棋盘的每一行恰好包含一个皇后可能会很有用。这意味着您实际上并不需要一个 8x8 矩阵来表示解决方案:一个 8 元素的列位置数组就可以了。

编辑针对您在 cmets 中的问题,这里是一个完整的 Python 实现,演示了上面的第 3 点:

def can_place(col_positions, col):
  row = len(col_positions)
  for r, c in enumerate(col_positions):
    if c == col or abs(c - col) == abs(r - row): return False
  return True

def queens(n, col_positions = []):
  if len(col_positions) >= n:
    pretty_print(n, col_positions)
    return True
  for col in xrange(n):
    if can_place(col_positions, col):
      if queens(n, col_positions + [col]):
        return True
  return False

def pretty_print(n, col_positions):
  for col in col_positions:
    print '.' * col + 'X' + '.' * (n - 1 - col)

queens(8)

【讨论】:

  • thx 得到了修复,当我通过引用传递它时,矩阵仍然存在问题,我应该将 *** 放在函数中并在 main 中使用 & 在前面调用矩阵吗?
  • @Lucian Enache:很难说剩下的问题是什么,但是从双指针到三指针几乎肯定不会解决它。
  • 所以你认为我使用矩阵的方法是错误的,我应该依赖数组吗?
  • @Lucian Enache:我不认为这是错误的,但我确实认为它不必要地复杂。
  • 你会如何解决这个问题?
【解决方案2】:

您的矩阵必须从 0 迭代到 MAX-1,

int **mat=  malloc(sizeof(int *)*MAX);
  for(i=0;i< MAX;i++){  //see for i<MAX
      mat[i]=  malloc(MAX*sizeof(int));               
      for(j=0;j<MAX;j++){ //see for j<MAX

           mat[i][j]=-1;
      }                        
   }

【讨论】:

    【解决方案3】:

    在 i 和 j 循环中必须使用 sizeof(...) * (MAX+1) 调用 malloc。

    此外,当我运行您的程序时,由于代码尝试访问 ma​​t[ri][c+j] 计算结果为 ma​​t[-1][1],因为 r==1i==2

    所以你对矩阵的对角线的描述似乎存在逻辑错误。

    【讨论】:

    • 内存分配肯定是个问题(但显然不是唯一的问题)。
    • @aix:你是对的。 malloc 必须用 sizeof(int)*(MAX+1) 调用
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    相关资源
    最近更新 更多