版权声明:转载请注明出处 https://blog.csdn.net/weixin_41238584/article/details/83280057
2018/10/22
问题描述
N(N为偶数)个高矮不同的人排成两排照相,要求每一排都是从矮到高排列,而第二排每个人比第一排对应的人要高,列出所有可能的结果。
输入格式
第一行正整数N(0<N<100)
第二行第一个人的身高h1
第三行第二个人的身高h2
…
第N+1行第N个人的身高hN
输出格式
1.每种情况占据一行;
2.将第一排按照排队顺序输出身高,然后将第二排按照排队顺序输出身高;
3.身高之间加空格(第二排最后一人后面为换行符,无空格),两排之间不加换行符(第一排最后一人与第二排第一人之间为空格)。
4.最后统计所有情况数目并输出。
输入样例
4
161
162
164
163
输出样例
161 162 163 164
161 163 162 164
2
或者下列输出也正确(即不同情况之间可交换顺序):
161 163 162 164
161 162 163 164
2
提示
1.使用<stdio.h>中的scanf,printf。它们比<iostream>中的cin, cout更快。
样例输入有两种排队方式,每种排队方式输出的顺序如图中红线所示:
其中,第一种排队方式对应输出如图所示,第二种同理。
2.每种情况输出完成后要换行。
3.在输出时,不同情况的输出先后顺序不影响答案的正确性。
不知道为什么OJ的题目跟学的内容没啥关系(大雾)。
我的算法是这样的:先把身高顺序排列,从中取一个数填到第二排首位(这个数从哪个范围中取要仔细考虑),再把剩下的数中最小的填到下面(你可以这么想:如果不取最小的数,那么必定有一个比它更小的数在右边某个位置或者某个位置的上方,这是不可能的。)然后就是……递归。
#define _CRT_SECURE_NO_WARNINGS //VS2010以上编译器
#include <stdio.h>
int n = 0;
struct MyArray{
int value;
bool used;
MyArray(){ used = false;}
};
void perm(MyArray *array,int **queue,int k,int num){
int i,j;
if(k>=num/2){
for(int i=0;i<num/2;++i) printf("%d ",queue[1][i]);
for(int i=0;i<num/2;++i) printf("%d ",queue[0][i]);
printf("\n");
++n;
}
else{
for(i=2*k+1;i<=num/2+k;++i){
if((!array[i].used)&&(k?(array[i].value>queue[0][k-1]):1))
{
queue[0][k] = array[i].value;array[i].used = true;
for(j=k;j<num;++j){
if(!array[j].used){
queue[1][k] = array[j].value;array[j].used = true;break;
}
}
perm(array,queue,k+1,num);
array[i].used = false;array[j].used = false;
}
}
}
}
void sort(MyArray *a,int num){
int s,i,j;
for(i=0;i<num;++i){
for(j=num-1;j>i;--j){
if(a[j-1].value>a[j].value){
s=a[j-1].value;a[j-1].value=a[j].value;a[j].value=s;}}}
}
int main(){
int Num,i;
scanf("%d",&Num);
MyArray *Array = new MyArray[Num];
for(i=0;i<Num;++i) scanf("%d",&(Array[i].value));
sort(Array,Num);
int **Queue = new int *[2];
for(i=0;i<2;++i) Queue[i] = new int [Num/2];
perm(Array,Queue,0,Num);
printf("%d\n",n);
delete []Array;Array = NULL;
for(i=0;i<2;++i){
delete []Queue[i];Queue[i] = NULL;
}
return 0;
}