思想:分析一下排列法,发现:每次安插第二排时,只要等第一排的选完了,再选最小值就行了。而选第一排时,只能从上次选的后一个开始选,且最后至少留count-1个数,count当前还剩多少个位置要安插!
//============================================================================ // Name : arrange12men.cpp // Author : // Version : // Copyright : // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <algorithm> #include <utility> #include <cstdio> using namespace std; void pr_arrByAux(int arr[], int len, int aux[]) { int i = 0; printf("\n(1): "); for (i = 0; i < len; i++) if (aux[i] == 1) printf("%-4d", arr[i]); printf("\n(2): "); for (i = 0; i < len; i++) if (aux[i] == 2) printf("%-4d", arr[i]); printf("\n"); } //把第一个为0的数放在队列2中,并返回当前位置 int set2(int aux[], int len,int lastI2) { int i = lastI2+1; for (; i < len; i++) if (aux[i] == 0) { aux[i] = 2; return i; } return -1; } //找到可以放到队列1的第一个位置 int findFirst1(int aux[], int len, int lastIndex) { int i=-1; for (i = lastIndex + 1 ; i < len && aux[i]!=0; i++); return i; } /*安插队列1 * count表示还有几个人安插,lastI1表示上次安插的位置,pout表示共用多少种安插法 * lastI2表示上次安插队列2的位置 */ void arrange1(int s[], int len, int count, int aux[], int lastI1,int lastI2,int *pout) { if (count == 0) { pr_arrByAux(s, len, aux); ++*pout; return; } int f1 = findFirst1(aux, len, lastI1); for (int i = f1; i <= len - count; i++) { aux[i] = 1; int j = set2(aux, len,lastI2); arrange1(s, len, count - 1, aux, i,j,pout); aux[i] = 0; aux[j] = 0; } } int arrange(int *s, int len) { int sum=0; int *aux = new int[sizeof(int) * len](); aux[0]=2; arrange1(s, len, 6, aux, 0, 0,&sum); return sum; } int main() { int s[] = { 1, 2, 3, 5, 6, 67, 23, 56, 87, 34, 32, 45 }; int len = sizeof(s) / sizeof(*s); sort(s, s + len); int sum=arrange(s,len); cout << endl << "总数:" << sum << endl; return 0; }
总数为:132种