12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第一排比对应的第二排的人高,问排列方式有多少种?
思想:分析一下排列法,发现:每次安插第二排时,只要等第一排的选完了,再选最小值就行了。而选第一排时,只能从上次选的后一个开始选,且最后至少留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种