Permutation

http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=5

Problem Id: 5
Submit time: 2012-03-06 21:04:57
User_id: 10839
Memory:152K   Time:6MS
Language:G++  Result:Accepted

  • Code
#include<iostream>
#include<algorithm>

const int N=1030;

int data[N],bk[N],n;
void print(int n,int* d)
{
	for(int i=0;i<n-1;i++)
		cout<<d[i]<<" ";
		cout<<d[n-1]<<endl;
		return;
}
void cpy(int* s,int* d)
{
	for(int i=0;i<n;i++)
		d[i]=s[i];
		return;
}
int main()
{
   int k,test,idx;
   cin>>test;
   while(test--)
   {
	   cin>>n>>k;
	   idx=0;
	   for(int i=0;i<n;i++)
	   {
		   cin>>data[i];
		   bk[i]=i+1;
	   }
		   while(idx<k&&next_permutation(data,data+n))
		    idx++;
		if(idx==k)
			print(n,data);
		while(idx<k)
		{
			idx++;
			cpy(bk,data);
			while(idx<k&&next_permutation(data,data+n))
				idx++;
			if(idx==k) print(n,data);
		}
	   
   }
	return 0;
}

next_permutation的简单应用,其实通过查看源码发现其算法设计的巧妙

1 2 3 4----->3 2 1

1 2 4 3----->3 2 0

-----

4 3 1 2----->0 0 1 

4 3 2 1----->0 0 0 

其实左边和右边存在一一对应的关系,右边的三个数的意义是 

1 2 3 4----->3 2 1: 1后面比1大的数有 ‘3’个,2后面比2大的数有‘2’个,3后面比3大的数有‘1’个,4因为在最后所以其后比他大的数不存在可以省去。

如果给右边的3个数字 每一位赋予一个阶的话,就可以用一个数来表示3个数了

关键就在于如何设计阶:

                  (3*3+2)*2+1=23

                  (3*3+2)*2+0=22

       (3*3+1)*2+1=21

----------------

                  (0*3+0)*2+0*1=0

所以说用0~23即可以代表任何一个排列 

也就是说 18所代表的排列的下一个排列为17 =(2*3+2)*2+1 也就是排列 2 1 3 4

 

posted @ 2012-03-06 21:24  wuzhibin  阅读(198)  评论(0编辑  收藏  举报