1. 程式人生 > 實用技巧 >mysql中union和union all

mysql中union和union all

例題:

n皇后問題

Problem Description:
在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input:
共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。

Output:
共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

思路:

在全排列上進行求解,由於當達到遞迴邊界時表示生成了一個排列,所以需要在其內部判斷是否為合法方案,即遍歷每兩個皇后,判斷他們是否在同一條對角線上,如果不是則累計計數變數count。採用列舉法

程式碼:

int count=0;
void generateP(int index){
    if(index==n+1){//遞迴邊界,生成一個排列 
        bool flag=true;
        for(int i=1;i<=n;i++){//遍歷任意兩個皇后 
            for(int j=i+1;j<=n;j++){
                if(abs(i-j)==abs(P[i]-P[j])){//如果再一條對角線上 
                    flag=false; 
                }
            }
        }
        
if(flag){ count++; } return ; } for(int x=1;x<=n;x++){ if(hashTable[x]==false){ P[index]=x; hashTable[x]=true; generateP(index+1); hashTable[x]=false; } } }

回溯法:

一般來說,如果在到達遞迴邊界前的某層,由於一些事實導致已經不需要往任何一個子問題遞迴,就可以返回上一層。

void generateP(int index){
    if(index==n+1){//遞迴邊界 
        count++;
        return; 
    }
    for(int x=1;x<=n;x++){//第x行 
        if(hashTable[x]==false){//第x行沒有皇后 
            bool flag=true;//flag為true表示當前皇后不會和之後的皇后衝突 
            for(int pre=1,pre<index;pre++){//遍歷之前的皇后 
                //第index列皇后的行號x,第pre列皇后的行號為P[pre] 
                    if(abs(index-pre)==abs(x-P[pre])){
                    flag=false;//與之前的皇后在同一條對角線上 
                    break;
                }
            }
            if(flag){//如果可以把皇后放在第x行 
                P[index]=x;//令第index列皇后的行號為x 
                hashTable[x]==true;//第x行已被佔用 
                generateP(index+1);//遞迴處理第index+1行皇后 
                hashTable[x]=false;//遞迴完畢,還原第x行為未佔用 
            }
        }
    }
}