标签:
vijosP1092 全排列
【思路】
数学+搜索。
根据序号依次确定每一个数。
首先我们可以把未选的数看作一个可选择集合,其次把寻找过程看作一棵树上的操作,如果有n个数我们已经确定了d个数,那么无论第d+1个数为多少以当前可选择集合中的任意一个数为根的子树的大小为(n-d-1)! 由此我们可以根据序号继续搜索。
注意:选择k的含义为选择了当前可选择集合中第k小的数。
详见代码
【代码】
1 #include<iostream> 2 #include<cstdlib> 3 using namespace std; 4 5 typedef long long LL; 6 int n; 7 LL m; 8 int A[25]; 9 int vis[25]; 10 11 void dfs(int d,LL num) { 12 if(d==n) { 13 for(int i=0;i<d;i++) cout<<A[i]<<" "; 14 exit(0); 15 } 16 LL tmp=1; 17 for(int i=1;i<=(n-d-1);i++) tmp *= i; 18 for(int k=1;k<=n;k++) 19 if((k-1)*tmp<=num && num<=k*tmp) { 20 int cnt=0; int i; 21 for(i=1;i<=n;i++) if(!vis[i]) if(++cnt==k) break; 22 vis[i]=1; A[d]=i; 23 dfs(d+1,num-(k-1)*tmp); 24 } 25 } 26 27 int main() { 28 cin>>n>>m; 29 dfs(0,m); 30 return 0; 31 }
注:本题与紫书P323 Password一题类似。
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/4874857.html