點擊上方藍字關注"程序員Bob"呀~程序員
孩子不是圖畫練習冊,你不能爲所欲爲塗上你想要的顏色。web
——《追風箏的人》算法
問題描述:輸入一個整數n,輸出對應的n皇后問題的解的個數
在解決N皇后問題以前,咱們得知道皇后問題的來源。微信
首先最開始的是八皇后問題,是由國際西洋棋棋手馬克斯·貝瑟爾於1848年提出的問題,也是回溯算法的典型案例。app
起初問題表述爲:在8×8格的國際象棋上擺放8個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。高斯認爲有76種方案。1854年在柏林的象棋雜誌上不一樣的做者發表了40種不一樣的解,後來有人用圖論的方法解出92種結果。若是通過±90度、±180度旋轉,和對角線對稱變換的擺法當作一類,共有42類。函數
固然,隨着計算機的發展,如今咱們能夠用程序來解決此類問題。
學習
下面代碼用到棧的知識,用棧裝載了每一行放置的皇后的座標,經過入棧與出棧,實現回溯。棧的結構爲雙鏈表結構。flex
源代碼以下:ui
typedef struct Queen{ int x; int y;}Queen;
typedef struct ListNode{//創建結點 Queen q; struct ListNode *Next;//指向前一個結點 struct ListNode *Last;//指向後一個結點}ListNode;
typedef struct List {//創建雙向鏈表 struct ListNode *header; struct ListNode *trailer; int _size;}List;
void CreateList(List *l);void InsertList(List *l,Queen e);Queen PopList(List *l);void InsertBefore(int i,Queen e,List *l);
void CreateList(List *l){ l->_size=0; l->header= (ListNode*)malloc(sizeof(ListNode)); l->trailer=(ListNode*)malloc(sizeof(ListNode)); l->header->Next=l->trailer; l->header->Last=NULL; l->trailer->Last=l->header; l->trailer->Next=NULL;}
void InsertList(List *l,Queen e){//在尾結點以前插入數據 ListNode *np=(ListNode*)malloc(sizeof(ListNode)); np->q.x=e.x; np->q.y=e.y; np->Next=l->trailer; np->Last=l->trailer->Last; l->trailer->Last->Next=np; l->trailer->Last=np; l->_size++;}
void InsertBefore(int i,Queen e,List *l){//在第i項前插入e int j; ListNode *p=l->header->Next; for(j=0;j<i;j++){ p=p->Next;//定位到第幾項 } ListNode *np=(ListNode*)malloc(sizeof(ListNode)); np->q.x=e.x; np->q.y=e.y; np->Next=p; np->Last=p->Last; p->Last->Next=np; p->Last=np; l->_size++;}
void PushList(List *l,Queen e){//入棧 ListNode *np=(ListNode*)malloc(sizeof(ListNode)); np->q.x=e.x; np->q.y=e.y; np->Last=l->header; np->Next=l->header->Next; np->Next->Last=np; l->header->Next=np; l->_size++;}
Queen PopList(List *l){//出棧 ListNode *now=l->header->Next; Queen old=now->q; now->Next->Last=now->Last; l->header->Next=now->Next; free(now); l->_size--; return old;}
int placeQ(int N){ int solution_n = 0; int i; List solution; CreateList(&solution); Queen q; q.x=0; q.y=0; int *xarray=(int*)calloc(N,sizeof(int)); int *yarray=(int*)calloc(N,sizeof(int)); int *sumarray=(int*)calloc(2*N,sizeof(int)); int *diffarray=(int*)calloc(2*N,sizeof(int)); for(i=0;i<N;i++){ xarray[i]=yarray[i]=0; } for(i=0;i<N*2;i++){ sumarray[i]=diffarray[i]=0; } do{ if(N<=solution._size ||N<=q.y) { Queen tmp = PopList(&solution); q.x = tmp.x; q.y = tmp.y; xarray[q.x]=0;//防止行衝突 yarray[q.y]=0;//防止列衝突 sumarray[q.x+q.y]=0;//存儲信息,防止對角線衝突 diffarray[q.x-q.y+N]=0;//防止另外一條對角線衝突 q.y++; } else { while ((q.y < N) && ((xarray[q.x] == 1) || (yarray[q.y] == 1) || \ (sumarray[q.x + q.y] == 1) || (diffarray[q.x - q.y + N]) == 1)) { q.y++; } if (N > q.y) { PushList(&solution, q); xarray[q.x] = 1; yarray[q.y] = 1; sumarray[q.x + q.y] = 1; diffarray[q.x - q.y + N] = 1; if (N <= solution._size) { solution_n++; } q.x++; q.y = 0; } } } while((q.x>0)||(q.y<N)); return solution_n;}
int main() { int num; scanf("%d",&num); //scanf_s("%d",&num); //進行邊界檢查,VS支持 //printf_s("%d",placeQ(num));//檢查字符是否有效 printf("%d",placeQ(num)); return 0;}
運行結果以下:
url
最後的話:刷題要找本身的不足,而後去專攻。
往期推薦:
2020-12-01
2020-11-28
2020-11-26
爲你,千千萬萬遍.
關注程序員Bob公衆號,與你一塊兒終生學習
本文分享自微信公衆號 - 程序員Bob(gh_8a1a1530d0bf)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。