生成字典排序的下个排列。(POJ—1833)

生成下一个排列的字典序法

字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是54321。
字典序算法如下:
设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即  j=max{i|pi 2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pj,pk
4)再将pj+1......pk-1pjpk+1pn反转,这就是排列p的下一个下一个排列。
题目描述: 
给出某个排列,求出这个排列的下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。 

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
代码如下:
#include
void get(int z,int a[],int y[])
{
	int i,l;
	int s=-1,p;
	for(i=z-1;i>0;i--)
	{
		if(a[i-1]		{
			s=i-1;
			l=i;
			break;
		}
	}
	if (s == -1)
	{
		for(i=0;i		{
			y[i]=i+1;
		}
		
	}
	else 
  {
		for(i=s+1;i		{
			if (a[i] > a[s])
			{
				if ((a[l] - a[s])>(a[i]- a[s]))
				{
					l=i;
				}
			}
		}


	p=a[l];
	a[l]=a[s];
	a[s]=p;
	for(i=s+1;i<(s+z)/2+1;i++)
	{
		p=a[i];
		a[i]=a[z-i+s];
		a[z-i+s]=p;
	}
	for(i=0;i	{
			y[i]=a[i];		
	}
   }
}
int main (void )
{
	int N;//输入测试的数据组数
	scanf("%d",&N);
	int i;
	int x,y;
	while(N)
	{
		scanf("%d%d",&x,&y);
		int a[x];
		int b[x];
		for(i=0;i		{
			scanf("%d",&a[i]);
		}
		get(x,a,b);
		while(y-1)
		{
          for(i=0;i			   a[i]=b[i];
		    }
		  get(x,a,b);
		  y--;	
		}
		for(i=0;i		{
			printf ("%d ",b[i]);
		}
		printf("\n"); 
		N--; 
	}
	

你可能感兴趣的:(C语言)