12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人 高,问排列方式有多少种?

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种

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值