排列(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;
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章