求当前排列的下K个排列:
(1):当当前排列为逆序排列时(最后一个排列), 下一个排列为:1 2 3 4 ....N
(2):下K次排列, 每次改变一次排列, 要考虑(1)
(3):要得到下一次排列, 从An开始, 当Ai > Ai-1时, 将Ai ~An从小到大排序, 在Ai ~ An中找出第一个大于Ai-1的数,
交换, 再将Ai ~ An从小到大排序就得到相应的下一个排列。
用include <algorithm>中的next_permutation(), 也可以很快求出排列
交换时用第0号元素当中间变量, 实现交换, 不知怎么的当时交换的方式乱七八糟的, 就错了几次....唉
Accepted 144K 547MS C 2115B 2010-11-25 19:53:32
#include <stdio.h>
#include <stdlib.h>
/* 判断是否是最后一个排列 */
char is_last_per(int *num, int n)
{
int i;
for (i = 1; i < n; i++)
{
if (num[i] > num[i+1])
{
continue;
}
else
{
return '0';
}
}
return '1';
}
/* 快速排序 */
void quick_sort(int *num, int *begin , int *end)
{
int *i, *j;
if (end - begin <= 1)
{
return;
}
i = begin;
j = end - 1;
num[0] = *begin;
while (i < j)
{
while (i < j && num[0] <= *j)
{
j--;
}
if (i < j)
{
*i = *j;
i++;
}
while (i < j && num[0] >= *i)
{
i++;
}
if (i < j)
{
*j = *i;
j--;
}
}
*j = num[0];
quick_sort(num, begin, j); /* 左边 */
quick_sort(num, j + 1, end); /* 右边 */
}
/* 输出 */
void print(int *num, int n)
{
int i;
for (i = 1; i <= n; i++)
{
printf("%d", num[i]);
if (i != n)
{
putchar(' ');
}
else
{
putchar('\n');
}
}
}
/* 设置下一个排列 */
void set_per(int *num, int n)
{
int i, j;
char is_last; /* 判断是否是最后一个排列 */
is_last = is_last_per(num, n);
if (is_last == '1') /* 不是最后一个排列 */
{
for (i = 1; i <= n; i++)
{
num[i] = i;
}
}
else
{
for (i = n; i > 1; i--)
{
if (num[i] > num[i-1])
{
quick_sort(num, &num[i], &num[n+1]); /* 一共两次排序 */
for (j = i; j <= n; j++)
{
if (num[i-1] > num[j])
{
continue;
}
else /* 交换 */
{
num[0] = num[i-1];
num[i-1] = num[j];
num[j] = num[0];
break;
}
}
quick_sort(num, &num[i], &num[n+1]); /* 一共两次排序 */
return;
}
else
{
continue;
}
}
}
}
/* 第k个排列 */
void k_permutation(int num[], int n, int k)
{
while ( k-- ) /* k次排列, 每次改变一次 */
{
set_per(num, n); /* 设置下一个排列 */
}
}
int main()
{
int cas, n, k, i, *num;
scanf("%d", &cas);
while ( cas-- )
{
scanf("%d%d", &n, &k);
if ((num=(int *) calloc (n + 1, sizeof(int))) == NULL)
{
printf("空间分配失败!\n");
exit(-1);
}
for (i = 1; i <= n; i++)
{
scanf("%d", &num[i]);
}
k_permutation(num, n, k); /* 下k个排列后 */
print(num, n);
free( num );
num = NULL;
}
}
/*问题描述大家知道,给出正整数n,则1 到n 这n 个数可以构成n!种排列,把这些排列按照从小到大的顺序
(字典顺序)列出,如n=3 时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1六个排列。给出某个排列,
求出这个排列的下k 个排列,如果遇到最后一个排列,则下1 排列为第1 个排列,即排列1 2 3…n。
比如:n = 3,k=2 给出排列2 3 1,则它的下1 个排列为3 1 2,下2 个排列为3 2 1,因此答案为3 2 1。
输入数据第一行是一个正整数m,表示测试数据的个数,下面是m 组测试数据,每组测试数据第一行是2 个正整数n
( 1 <= n < 1024 )和k(1<=k<=64),第二行有n 个正整数,是1,2 … n的一个排列。
输出要求对于每组输入数据,输出一行,n 个数,中间用空格隔开,表示输入排列的下k 个排列。
输入样例33 12 3 13 13 2 110 21 2 3 4 5 6 7 8 9 10
输出样例3 1 21 2 31 2 3 4 5 6 7 9 8 10*/