排列(poj1833)

poj 1833 排列

Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 24036 Accepted: 8727
Description

题目描述:

大家知道,给出正整数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。

Input

第一行是一个正整数m,表示测试数据的个数,下面是m组测试数据,每组测试数据第一行是2个正整数n( 1 <= n < 1024 )和k(1<=k<=64),第二行有n个正整数,是1,2 … n的一个排列。

Output

对于每组输入数据,输出一行,n个数,中间用空格隔开,表示输入排列的下k个排列。

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

问题链接: 题目来源

解题思路:

这是一道经典的模拟问题,使用模拟法解题时注意对问题进行分析然后抽离主要步骤,将现实的实物映射成计算机能够识别的符号代码,而将现实实物之间的关系分别映射成运算或逻辑控制流。

模拟法通常不需要高超的算法技巧,只需要读者可以理解问题,抓住问题的关键,对于没有一些具体数值解法的题目来讲,模拟法是最好的办法。

这道题的大意为给定一个序列 cnt[n] 求出这个序列后第 k 个序列,例如序列 1、2、3 的后的第2个序列为 2、1、3。

我的想法如下图:

而该算法的关键在于找到给定排列的下一个排列:

  1. 使用C++ 库中的next_permutation( ) 函数。

    具体用法为:

    int a[]={1,2,3,4,5}; //产生所有下一组合,时间复杂度为n!,速度较慢
    next_permutation(a,a+5); //求出a序列的后第5个序列。

  2. 当然如果你不知道这个函数的话也可以自己造轮子,具体思路如下:
    在这里插入图片描述
    具体ac代码如下:

#include<bits/stdc++.h> //万能头文件有些编译器可能不能通过
using namespace std;
int m, n, k;       //m为测试个数 n为 n个正整数组成排列 k为后面第几个排列 
#define MAXN 1030
int cnt[MAXN] = {0};

void NextPermutation(int size)   //找出此排列后的最小排列 
{
	int flag = size - 1; //先默认最右边为标志 假设是最大的数字
	
	while(cnt[flag-1] > cnt[flag] && flag != 0)
		flag--;  //得出flag为从右往左数 左边的的数字小于此数的数字(或者为 0的数字) 设该数字为min数 
		
	if(flag == 0)
	{
		for(int i = 0; i < size; i++)
			cnt[i] = i + 1;
		return;
	} 
	
	for(int i = size - 1; i >= flag; i--)
	{
		if(cnt[i] > cnt[flag -1])
		{
			swap(cnt[i], cnt[flag - 1]);   //找到第一个从左往右数第一个大于flag 左边的数字 
			break;	
		}	
	}
	
	//重新排列flag右边的数字 从小到大排列
	
	while(size -1 > flag)
	{
		swap(cnt[flag], cnt[size - 1]);
		flag ++;
		size --;
	  }  
	 
 } 

int main()
{
	scanf("%d",&m); //表示测试的个数共有m 个
	while(m--)
	{
		scanf("%d%d", &n, &k);
		for(int i = 0; i < n; i++)
			scanf("%d", &cnt[i]);
		for(int i = 0; i < k; i++)
			NextPermutation(n);  //重复求cnt的下一个排列 更新cnt 
		for(int i = 0; i < n; i++)
			printf("%d ", cnt[i]);
			printf("\n");
	 } 
	return 0;
 } 
发布了5 篇原创文章 · 获赞 4 · 访问量 103

猜你喜欢

转载自blog.csdn.net/qq_44953321/article/details/104089313