问题描述:
12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
基本思路:
假设分为a,b两列,则排列如下:
a1,a2,a3,a4,a5,a6
b1,b2,b3,b4,b5,b6
由题意可知,两个序列是递增序列,此外,b1>a1,b2>a2,b3>a3,b4>a4,b5>a5,b6>a6
由这些已知条件我们发现一个规律,在2*n序列当中,右下角所指的数将是两个序列最大的数
比如,b6是2×6序列当中最大的,b5是2*5序列当中最大的。
所以我们的算法思想就是从n=6开始,先求出2×n序列当中右下角最大的数,继而再利用限制条件求出该数对应的上面序列的数。
比如:在n=6时,2*6序列的右下角,即第二行第六个,12肯定是最大的数,所以 该数填充为12,12对应上面的数的位置就是第一行第六个数a6,a6要满足a6>=6,否则第一列前面五个数必然会出现一个数比a6大
在确定b6,a6之后,b6和a6将从一至12的高矮序列中排除,剩下当中最高的将作为2*5序列右下角当中最高的,故b5位置将由剩下十人当中最高的填充,其所对应的a5将满足a5>=5此外a5
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int coun;
void twoSeries(int n,int rLim,vector<int> people)
{
people.pop_back();//剔除最高的,最开始是剔除b6
if(n==1)
coun++;
for(int i=n;i<rLim;i++) //左边限制条件n与右边限制条件rLim
{
vector<int> temp=people;
vector<int>::iterator it;
it=temp.begin();
temp.erase(it+i);//在填充好序列之后刎除
if(i<temp.size()) //该判断条件用来比较第一列的右邻和下邻的大小以确定右边界
twoSeries(n-1,i,temp); //注意i=temp.size()的特殊情况
else
twoSeries(n-1,rLim-2,temp);
}
}
int main()
{
vector <int> people;
for(int i=0;i<=12;i++)
{
people.push_back(i);
}
twoSeries(6,12,people);
cout<<coun<<endl;
}