多種解法解決n皇後問題
阿新 • • 發佈:2019-04-12
簡潔 不同 include top sca 方法 stl isp name
多種解法解決n皇後問題
0x1 目的
? 深入掌握棧應用的算法和設計
0x2 內容
? 編寫一個程序exp3-8.cpp求解n皇後問題。
0x3 問題描述
即在n×n的方格棋盤上,放置n個皇後,要求每個皇後不同行、不同列、不同左右對角線。
要求:(1)皇後的個數n由用戶輸入,其值不能超過20,輸出所有的解。(2)采用類似於棧求解迷宮問題的方法。
0x4 遞歸解法
#include <iostream> #include <cstdio> #include <cstdlib> #include <string.h> #define maxsize 20+7 using namespace std; int y_pos[maxsize]; int n; int count=0; bool judge(int num) { for(int i=0;i<num;i++) { if(y_pos[i]==y_pos[num] || abs(y_pos[num]-y_pos[i])==num-i) return false; } return true; } void show() { printf("\nThe %d number position:\n",count); for(int i=0;i<n;i++) { printf("\t(%d,%d)",i,y_pos[i]); } } void RecurBack(int num) { if(num==n) { count++; show(); return; } for(int i=0;i<n;i++) { y_pos[num]=i; if(judge(num)) { RecurBack(num+1); } } } int main() { printf("input n:\n"); scanf("%d",&n); memset(y_pos,0,sizeof(y_pos)); RecurBack(0); printf("\ncount:%d",count); return 0; }
思路就是: 直接從不同行開始選取,然後判斷是否滿足條件。思路主要就是以皇後的個數作為行數,然後遞歸下去,遞歸出口就是回溯
0x5 全排列解法
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #define maxsize 20+7 using namespace std; int queen[maxsize]; int n; int count_=0; int main() { printf("input n:\n"); scanf("%d",&n); for(int i=0;i<n;i++) { // Init array queen[i]=i; } do { /* for(int i=0;i<n;i++) printf("%d\t",queen[i]); printf("\n"); */ // generate the permutation of queen bool find=true; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(j-i==abs(queen[j]-queen[i])) { //cout<< "false!!! " <<endl; find=false; break; } if(!find) break; } } //printf("\n"); if(find) { count_++; } }while(next_permutation(queen,queen+n)); printf("count:%d",count_); return 0; }
這個可以來說也很好,都是暴力解法,時間差別主要是在生成全排列的過程,但是這個解法可以利用STL,代碼可以說是相當簡潔的了。
0x6 用棧解決
? 用棧來模擬遞歸過程,這個是我數據結構的一個作業。
#include <iostream> #include <cstdio> #include <cstdlib> #include <string.h> #define MaxSize 100000+7 #define maxsize 20+7 using namespace std; int path[maxsize][maxsize]; int n; int y_pos[maxsize]; int count=0; bool judge(int num) { for(int i=0;i<num;i++) { if(y_pos[i]==y_pos[num] || abs(y_pos[num]-y_pos[i])==num-i) return false; } return true; } typedef struct { int x; int y; int di; }Box; typedef struct { Box data[MaxSize]; int top; }StType; void InitStack(StType *&s) { s=(StType *)malloc(sizeof(StType)); s->top=-1; } void DestroyStack(StType *&s) { free(s); } bool GetTop(StType *&s,Box &e) { if(s->top==-1) return false; e=s->data[s->top]; return true; } bool push(StType *&s,Box e) { if(s->top==MaxSize-1) return false; s->top++; s->data[s->top]=e; return true; } bool pop(StType *&s,Box &e) { if(s->top==-1) return false; e=s->data[s->top]; s->top--; return true; } int GetLength(StType *s) { return(s->top+1); } bool EmptyStack(StType *s) { return(s->top==-1); } void SetPath(int ex,int ey,int k) { int xi=ex; int yi=ey; for(int i=0;i<n;i++) { path[xi][i]+=k; path[i][yi]+=k; } int x1,x2,y1,y2; x1=x2=xi; y1=y2=yi; while(x1>0&&y1>0) path[--x1][--y1]+=k; while(x2<n&&y2<n) path[x2++][y2++]+=k; path[xi][yi]-=k*2; } void printSolution() { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(y_pos[i]==j) printf("q"); else printf("*"); } printf("\n"); } printf("\n"); } void Disp(StType *s) { for(int i=0;i<s->top;i++) printf("\t(%d,%d)",s->data[i].x,s->data[i].y); } void SolveQ(int n) { int x1,y1,di; StType *st; InitStack(st); Box e; e.x=0; e.y=-1; push(st,e); while(!EmptyStack(st)) { GetTop(st,e); x1=e.x; y1=e.y; bool find=false; if(x1==n) { printSolution(); Disp(st); printf("\n"); count++; } while(y1<n-1 && !find) { y1++; y_pos[x1]=y1; st->data[st->top].y=y1; if(judge(x1)) { find=true; e.x=x1+1; e.y=-1; push(st,e); } } if(!find) { pop(st,e); } //pop(st,e); } } int main() { printf("please input n:\n"); scanf("%d",&n); memset(path,0,sizeof(path)); memset(y_pos,0,sizeof(y_pos)); SolveQ(n); printf("\n count:%d \n",count); return 0; }
多種解法解決n皇後問題