[遞迴]使用棧解決n輛列車排程問題(列車編號1-n)
阿新 • • 發佈:2018-12-30
引言:
編號為1-n的n輛列車進棧,要獲得所有正確序列,則可以先通過獲得n輛列車的全排列,然後對每個排列進行正確性檢驗,
即可以獲得所有正確序列。正確性是基於引理,對於一個正確的出棧序列,如果有k<i<j,且a[j]<a[k],則必有a[i]<a[k],簡單來
說就是要滿足小於邊界的所有數必須正序排列。
本程式中,使用迴圈移位方法獲得全排列。迴圈移位的思路是給定一個序列1 2 3 4 .... n。遞迴層次多了很難表達,此處
用1234的思維導圖演示過程。(圖中所有連線均為雙箭頭,第一層遞迴順序是1234->2134->1324->3241->2413->4132->1324)
#include <stdio.h> #include <malloc.h> #include <string.h> void Permutation(int n); void Recursion(int *a,int n,int k); void Print(int *a,int n); void PrintError(int *a,int n); void GetStackList(int *a,int n,int k); static int flag = 0; static int errorNum = 0; static int totalNum = 0; int main() { Permutation(12); return 0; } void Permutation(int n) { int *a = (int *)malloc(sizeof(int)*n); for(int i=0;i<n;i++) { a[i] = i+1; } Recursion(a,n,2); printf("\ninfo:there are %d error list!\n",errorNum); printf("info:there are %d total list!\n",totalNum); free(a); } /** 通過遞迴獲得全排列,全排列獲得演算法採用迴圈移位法 迴圈移位次數 = 迴圈移位的元素個數 = k **/ void Recursion(int *a,int n,int k) { if(k > n) { flag = 0; totalNum++; GetStackList(a,n,n-1); } else { int temp; for(int i=0;i<k;i++) { temp = a[0]; for(int j=1;j<k;j++) a[j-1] = a[j]; a[k-1] = temp; Recursion(a,n,k+1); } } } /** 遞迴判斷序列是否正確,每一次判斷的過程是將每個序號和邊界進行大小判定 ,若比邊界大,重新修改邊界,再次重複判斷過程。若比邊界小,則該序列是 錯誤的。 **/ void GetStackList(int *a,int n,int k) { int end = a[k]; unsigned long temp = 4294967295; for(int j=k-1;j>=0;j--) { if(a[j] < end) { if(a[j] < temp) { temp = a[j]; continue; } if(a[j] > temp && flag != -1) { PrintError(a,n); flag = -1; errorNum ++; return; } } else { GetStackList(a,n,j); } } } void PrintError(int *a,int n) { printf("\nthis is error list:"); for(int i=n-1;i>=0;i--) { printf("%d ",a[i]); } printf("\n"); } void Print(int *a,int n) { for(int i=n-1;i>=0;i--) { printf("%d ",a[i]); } printf("\n"); }
n如果超過了10運算量很大,序號10以下所有排列大概有10×9×8×7....×1=300多萬種。
正確的出棧序列可以使用公式計算出來,F(n) = F(0) * F(n-1) + F(1) * F(n-2) + ....... + F(n-1) * F(n-n)
其中F(n-1) = F(0) * F(n-2) + F(1) * F(n-3) + ....... + F(n-1) * F(n-(n-1))
F(1) = F(0) = 1
F(2) = 2
F(3) = 5
F(4) = 14
F(5) = 42
F(6) = 132