所谓N元错位排列,就是指对应于1,2,--,N的N元排列Im(m=1,2,---,N),满足Im!=m,算法的目的是构造出所有这样的错位排列,依据的基本思想是回溯法,在沿栈向下试探的过程中逐步扩大部分错位排列的规模,当发现无法找到下一个部分错位排列的元素时就向上回溯,继续试探,当栈空间首元素stack[0]==N+1时,表明首元素为2,--,N的所有错位排列已全部试探得到,错位排列生成完毕,退出循环。这里给出算法,该算法生成对应于1,2,---,N的所有N元错位排列
代码(C++)
1 #include "stdafx.h" 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 6 #define N 5 //问题规模,生成对应于1,2,---,N的所有N元错位排列 7 8 int Search(const vector<bool> &occupy, int i ,int j) 9 { 10 for (; i < occupy.size(); ++i) 11 { 12 if (i + 1 != j && occupy[i] == false) 13 { 14 return i + 1; 15 } 16 } 17 return 0; 18 } 19 20 int main() 21 { 22 vector<int> a(N, 0); 23 vector<bool> occupy(N, false); //对于栈中已生成的错位排列中的任意值i,occupy[i-1]==true,对于1,2---,N中不在错位排列栈中的任意元素i,occupy[i-1]=false 24 bool TF = true; //循环过程中回溯至本层为false,前进至本层为true 25 int i = 0; //存放错位排列的栈的栈顶指针 26 int count = 0; //统计错位排列数 27 while (true) 28 { 29 if (i == 0) 30 { 31 if (TF == true) 32 { 33 a[i] = 2; 34 occupy[a[i] - 1] = true; 35 ++i; 36 } 37 else 38 { 39 occupy[a[i] - 1] = false; 40 ++a[i]; 41 if (a[i] > N) 42 break; 43 occupy[a[i] - 1] = true; 44 ++i; 45 TF = true; 46 } 47 } 48 else 49 { 50 int temp; 51 if (TF == true) 52 { 53 if ((temp = Search(occupy, 0, i + 1)) == 0) 54 { 55 --i; 56 TF = false; 57 continue; 58 } 59 else 60 { 61 a[i] = temp; 62 occupy[temp-1] = true; 63 } 64 } 65 else 66 { 67 if ((temp = Search(occupy, a[i], i + 1)) == 0) 68 { 69 occupy[a[i] - 1] = false; 70 --i; 71 continue; 72 } 73 else 74 { 75 occupy[a[i] - 1] = false; 76 a[i] = temp; 77 occupy[temp - 1] = true; 78 } 79 } 80 81 if (i != a.size() - 1) 82 { 83 ++i; 84 TF = true; 85 } 86 else 87 { 88 ++count; 89 cout << "第"<<count<<"个错位排列:" << endl; 90 for (const int &m : a) 91 { 92 cout << m << " "; 93 } 94 cout << endl; 95 for (int j = 1; j <= N; ++j) 96 { 97 cout << j << " "; 98 } 99 cout << endl; 100 cout << endl; 101 TF = false; 102 } 103 104 } 105 } 106 return 0; 107 }
运行结果(N=5时)
原文:https://www.cnblogs.com/WSKIT/p/9189279.html