N皇后問題,,回溯與迭代
窮舉法的例子,每行只能有一個,每列也只能有一個,整個棋盤共n個,可以以行為單位遍歷。從第一行開始,對行的每一列都進行判定,如果當前位置可以,則將其座標進棧,然後判斷下一行(因為一行只能有一個,當前行已經放置了),仍從第一列開始。當判斷到最後一行時,若有位置滿足,則一條路徑已經找到,輸出。否則,若最後一行所有列都遍歷完後仍不滿足,需要改變上一行的位置,尋找上一行中後面的可滿足的,更新棋盤,重點理解回溯的過程,queen(row+1)是在判斷第row行有一個合適位置(row,k)之後呼叫的,是在找k的for()迴圈中的。如一共有4行4列,當進行到queen(4)時,函式結束遞迴,輸出一個結果,刪除棧頂元素(最後一行的位置)此時queen(4)執行完成,返回到呼叫她的地方,即判斷第三行的(3,k),然後執行k++,繼續尋找第三行後面的可行位置。整個第三行找完以後,返回到(2,k'),進行k'++.....如此回溯,便可找到所有路徑。
#include<stdio.h> #include<stdlib.h> #include<math.h> #define STACK_INIT_SIZE 100 #define STACK_INCREMENT 10 #define max 10 #define overflow -1 #define error -1 typedef struct{ int row; int col; }ElemType; int tag=1; typedef struct{ ElemType * base; ElemType * top; int stacksize; int len; }SqStack;//棧用於存放路徑 //棧的基本操作 void InitStack(SqStack * S){//問題:define int Status 函式返回OK(1) 前面關於int會錯誤,,寫返回void 會有沒有影響? (*S).base=(ElemType *)malloc( STACK_INIT_SIZE*sizeof(ElemType)); if(!(*S).base) exit(overflow); (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; (*S).len=0; } void Push(int row,int col,SqStack * S){ ElemType e; e.row=row; e.col=col; if((*S).top-(*S).base>=(*S).stacksize){ (*S).base=(ElemType *)realloc((*S).base,((*S).stacksize+STACK_INCREMENT)*sizeof(ElemType)); if(!(*S).base) exit(overflow); (*S).top=(*S).base+(*S).stacksize; (*S).stacksize+=STACK_INCREMENT; } *(*S).top++=e; (*S).len++; } int Pop(SqStack *S){ ElemType e; if((*S).len==0) return error; e = *(--(*S).top); (*S).len--; }
void print_result(SqStack S){ ElemType * p=S.base; printf("%d: ",tag); for(;p<S.top;p++){ printf("(%d,%d) ",(*p).row+1,(*p).col+1); } printf("\n"); tag++; } int can_place(int row,int col,SqStack S){ ElemType * s=S.base; while(s<S.top){ if((*s).col==col) return 0; else if(abs(row-(*s).row)==abs(col-(*s).col))//開始寫成行減=1,是全部的上下對角線啊,不是緊鄰的 return 0; s++; } return 1; }
void queen(int row,int n,SqStack *S){ int k; if(row==n) { print_result(*S); Pop(S); } else{ for(k=0;k<n;k++){ if(can_place(row,k,(*S))){ Push(row,k,S); queen(row+1,n,S); } }//for if(k==n) Pop(S); //這一行沒有,刪除棧頂元素 }//else }
int main(){ int n; SqStack S; InitStack(&S); scanf("%d",&n);
queen(0,n,&S); return 0; }