bupt boj 第五题

题目
Permutation
Accept:217    Submit:706
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

/*************************************************************************
  > File Name: next_permutation.c
  > Author: narutolby
  > Mail:[email protected]
  > Created Time: 2013年01月08日 星期二 09时26分34秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
int num[1024];
typedef struct test1{
	int len;
	int nextP;
	int num[1024];
}Test;
void printfArray(int num[],int len){
	int	i=0;
	for(;i<=len;i++){
		printf("%d",num[i]);
		if(i<len){
			printf(" ");
		}
	} 
		printf("\n");
}
void swap(int num[],int i,int j){
	int t=0;
	t=num[i];
	num[i]=num[j];
	num[j]= t;
}
void reverse(int num[],int start,int end){
	for(;start<end;start++,end--){
		swap(num,start,end); 
	}
}
void next_permutation(int num[],int len,int k){
	int j=len;
	int loop = 0;
	while(j>0){
		if(num[j]>num[j-1]){
			int minMax = num[j],n=j+1,minMaxIndex=j;
			for(;n<=len;n++){
				if(num[n]<minMax && num[n]>num[j-1]){
					minMax = num[n];	
					minMaxIndex = n;
				}
			}
			swap(num,j-1,minMaxIndex);
			int f=j,g=len;
			reverse(num,f,g);
			loop++;
			if(loop==k){
				printfArray(num,len);	
				break;
			}
			j=len;
		}else{
			j--;
		} 
	}
	if(loop<k){
		reverse(num,0,len);
		loop++;
		if(loop==k){
			printfArray(num,len);	
		}else{
			next_permutation(num,len,k-loop);
		}
	}

}
int main(){
	int times,time=0;
	scanf("%d",&times);
	Test *testArray[times] ;
//	printf("times:%d\n",times);
	for(;time<times;time++){
//		printf("current time:%d\n",time);
		Test *test = (Test*)malloc(sizeof(Test));
		scanf("%d %d",&test->len,&test->nextP);
//		printf("%d %d\n",test->len,test->nextP);
		int m =0;
		for(;m<test->len;m++){
			scanf("%d",&test->num[m]) ;
//			printf("%d ",test->num[m]);
		}
	//	printf("\n");
		testArray[time] = test;
	}
//	printf("end\n");
	time=0;
	for(;time<times;time++){
		Test *t1 = testArray[time];
		next_permutation(t1->num,t1->len-1,t1->nextP);
		free(t1);
	}
	return 0;
}

解题思路
  本题的输入为int型数组array和int型k值,以当前数组开始,求第k个按字典顺序的全排列输出。
解题步骤
   所谓字典顺序,就是数组之间会从索引0开始,依次比较,如果相同,则比较下一个元素,直到遇到不同大小的元素为止,大元素所在的数组字典顺序在小元素所在数组的后面,依次类推。
  回到本题,如输入数组1,2,3,4,5为按照字典顺序的第一个,5,4,3,2,1为按照字典顺序的最后一个,也就是数字越大的数字所在的位置越靠前,所在的字典顺序越靠后。
  按照这个思路,所以我们的解题步骤如下:
(1)从后向前遍历数组,记录第一个当前元素大于前一个元素的位置,记录为i;
(2)从第i个元素开始,向后搜索大于i-1最小的元素,记录为j,交换i和j的元素值,并将从第i个元素开始以后的元素倒置。
经过以上两个步骤就求出了当前数组在字典顺序下的下一个全排列。
同理,可求出第k个。

你可能感兴趣的:(UP)