nBOJ5 - Permutation
Accept:113 | Submit:308 |
Time Limit:1000MS | Memory Limit:65536KB |
Description
We all know that , when there are n positive integers (namely 1…n) , we can use these n integers to construct n! kinds of permutations . Sort these permutations in lexicographic order . For example , when n = 3 , we can permute 1 2 3,1 3 2,2 1 3, 2 3 1, 3 1 2 , 3 2 1 these 6 kinds of permutations.
Now , we want to know , with the given permutation , calculate the next k permutation . If the permutation is the last permutation in order , its next permutation is the first permutation , namely 1 2 3 … n.
e.g. when n = 3 , k = 2 , giving the permutation 2 3 1 , thus its next 1 permutation is 3 1 2 , its next 2 permutation is 3 2 1 , so the answer is 3 2 1 .
Input
The first line is a positive integer m , indicating the number of test cases . Then m test cases . In every test case , the first line is 2 positive integers n (1 <= n < 1024) and k (1 <= k <= 64) ; the second line are n positive integers , which is one of the “ 1 2 3 … n” s’ permutation.
Output
For each test case , print one line , n numbers , with spaces separating every number , indicating the given permutation ‘s next k permutation.
Sample Input
3
3 1
2 3 1
3 1
3 2 1
10 2
1 2 3 4 5 6 7 8 9 10
Sample Output
3 1 2
1 2 3
1 2 3 4 5 6 7 9 8 10
其实刚看到的时候没什么思路。但是想到了STL的next_permutation,于是就搜了一下这个库函数的实现。
具体的操作是从右边开始搜两两相连的数,直至发现一组满足右边>左边,然后把左边的位置标记为x,然后从最右边开始搜索直至发现满足大于这个数的第一个数,将其位置标记为y,然后交换x与y位置的元素,然后将x之后的所有元素逆置。
比如序列1,5,3,4,2,6,8,9,10,7
第一组满足右边>左边的是[9,10],然后第一个大于9的元素是10,那么交换9和10元素的位置,然后将10之后所有元素逆置,既1,5,3,4,2,6,8,10,7,9
再看这组数列的下一排列,第一个满足右边>左边的是[7,9],那么下一排列是1,5,3,4,2,6,8,10,9,7
同理,再下一组排列的变化过程是
1,5,3,4,2,6,8,10,9,7 --> 1,5,3,4,2,6,9,10,8,7 --> 1,5,3,4,2,6,9,7,8,10
代码分析见:http://apps.hi.baidu.com/share/detail/19561533
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<numeric>
#include<cstdio>
using namespace std;
int main(void)
{
int m(0),n,k;
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&n,&k);
int *p = new int[n];
for(int i(0);i != n;++i)
scanf("%d",&p[i]);
while(k--)
if(!next_permutation(p,p+n))//返回值为false表示是最后一组排列,那么排序为升序即可回到第一组
sort(p,p+n);
for(int i(0);i != n-1;++i)
printf("%d ",p[i]);
printf("%d\n",p[n-1]);
delete[] p;
}
return 0;
}