/**
* 学生站队,要求站成两排,每一排都是从矮到高,并且后排的人比他前排的人高,问有多少种站法。
* 实际就是全排列问题,满足
* a[0]<a[2]<a[4]<a[6]
* a[1]<a[3]<a[5]<a[7]
* a[0]<a[1], a[2]<a[3], a[4]<a[5], a[6]<a[7]
*
* 再重复一遍字典序的步骤:
* 1 数组从小到大排序。
* 2 从右向左扫描,找到第一次出现左边的数小于右边的数,记下左边的数的位置为i。
* 3 从右向左扫描从n-1到i+1的数,选择所有比a[i]大的数中最小的那一个,因为是递增的,所以选择第一次出现比a[i]大的数,位置记为j。
* 4 交换a[i]和a[j]。
* 5 将a[i+1]至a[n-1]倒序。
*
*/
public class TwoLines {
public int line(int[] a) throws Exception{
if(a==null) return -1;
assert(a.length == 8);//假设8个学生
QuickSort.sort(a);
int count = 1;//显然,初始排列满足要求
int[] line = a;
while(line != null){
line = getASequence(line);
if(line != null){
if(isQualified(line)){
Tools.printArray(line);
count++;
}
}
}
return count;
}
/**
* 这里使用字典序生成全排列。
* @param a
* @return
*/
public int[] getASequence(int[] a){
int i = a.length - 1;
for(; i>0; i--){
if(a[i] > a[i-1]){
for(int j=a.length-1; j>i-1; j--){
if(a[j] > a[i-1]){
Tools.swap(a, i-1, j);
break;
}
}
Tools.reverseArray(a, i, a.length-1);
break;
}
}
if(i == 0){
return null;
}else{
return a;
}
}
private boolean isQualified(int[] a){
int v1 = -1;
int v2 = -1;
for(int i=0; i<a.length-1; i=i+2){
if(a[i+1] > a[i]){
if((a[i]>v1) && (a[i+1]>v2)){
v1 = a[i];
v2 = a[i+1];
}else{
return false;
}
}else{
return false;
}
}
return true;
}
/**
* @param args
*/
public static void main(String[] args) {
TwoLines o = new TwoLines();
int[] a = {1,2,3,4,5,6,7,8};
try {
int count = o.line(a);
System.out.println("--------->"+count);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}