hdu1027 next_permutation的应用
2017-09-15 20:49
330 查看
博文参考:http://www.cnblogs.com/luruiyuan/p/5914909.html讲的很棒
题目求n个数按字典序的第m个排列,有prev_permutation,next_permutation等现成函数。
在此介绍一下next_permutation的实现过程:
方便理解,首先对1,2,3,4,5这5个数进行分析:
1:将1,2,3固定,对4操作,易得1,2,3,5,4
2:将1,2,固定,对3操作,找到3后面大于3的最小数4,swap(3,4),得到1,2,4,5,3,此时5,3是个逆序,明显不满足,所以将5,3翻转,得到1,2,4,3,5
……
从上面的过程中可以发现当前序列的后面部分一定存在一个完全逆序的子序列,比如1,2,3,4,5的逆序子序列只有5,而1,2,3,5,4的逆序子序列则是5,4,很明显后面的逆序部分已经达到最大,想要下一步得到更大的排列,只能对前一位进行操作,对1,2,3,5,4而言,也就是3,这时我们选择的应该是后面部分大于3的最小数,也就是4,进行对调,易得,对调后后面部分依然是逆序,此时我们应该执行翻转操作,变成正序。
通过对上面的理解,prev_permutation也容易懂了(~
),我们应该寻找当前序列的后面正序部分,然后将前一位(设为x)与后面正序部分小于x的最大数,对调,然后翻转。bool next_permutation(int* start,int* end){
int *temp1=end-1,*temp2=temp1-1;
while(*temp1<=*temp2&&temp2<=start) temp2--,temp1--;//寻找正序
if(temp2<start) return false;
for(temp1=end-1;*temp1>=*temp2;temp1--);//寻找正序部分小于x的最大数
swap(temp1,temp2);
reverse(temp2+1,end);
return true;
}ac代码:#include<iostream>
#include<cstring>
using namespace std;
int s[1005];
void swap(int* s,int* e){
int t=*s;
*s=*e;
*e=t;
}
void reverse(int* s1,int* e1){
e1--;
while(s1<e1) swap(s1,e1),s1++,e1--;
}
bool next_permutation(int* start,int* end){
int *temp1=end-1,*temp2=temp1-1;
while(*temp1<=*temp2&&temp2>=start
4000
) temp2--,temp1--;
if(temp2<start) return false;
for(temp1=end-1;*temp1<=*temp2;temp1--);
swap(temp1,temp2);
reverse(temp2+1,end);
return true;
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++) s[i-1]=i;
for(int i=1;i<m;i++) next_permutation(s,s+n);
for(int i=0;i<n-1;i++) printf("%d ",s[i]);
printf("%d\n",s[n-1]);
}
return 0;
}
题目求n个数按字典序的第m个排列,有prev_permutation,next_permutation等现成函数。
在此介绍一下next_permutation的实现过程:
方便理解,首先对1,2,3,4,5这5个数进行分析:
1:将1,2,3固定,对4操作,易得1,2,3,5,4
2:将1,2,固定,对3操作,找到3后面大于3的最小数4,swap(3,4),得到1,2,4,5,3,此时5,3是个逆序,明显不满足,所以将5,3翻转,得到1,2,4,3,5
……
从上面的过程中可以发现当前序列的后面部分一定存在一个完全逆序的子序列,比如1,2,3,4,5的逆序子序列只有5,而1,2,3,5,4的逆序子序列则是5,4,很明显后面的逆序部分已经达到最大,想要下一步得到更大的排列,只能对前一位进行操作,对1,2,3,5,4而言,也就是3,这时我们选择的应该是后面部分大于3的最小数,也就是4,进行对调,易得,对调后后面部分依然是逆序,此时我们应该执行翻转操作,变成正序。
通过对上面的理解,prev_permutation也容易懂了(~
),我们应该寻找当前序列的后面正序部分,然后将前一位(设为x)与后面正序部分小于x的最大数,对调,然后翻转。bool next_permutation(int* start,int* end){
int *temp1=end-1,*temp2=temp1-1;
while(*temp1<=*temp2&&temp2<=start) temp2--,temp1--;//寻找正序
if(temp2<start) return false;
for(temp1=end-1;*temp1>=*temp2;temp1--);//寻找正序部分小于x的最大数
swap(temp1,temp2);
reverse(temp2+1,end);
return true;
}ac代码:#include<iostream>
#include<cstring>
using namespace std;
int s[1005];
void swap(int* s,int* e){
int t=*s;
*s=*e;
*e=t;
}
void reverse(int* s1,int* e1){
e1--;
while(s1<e1) swap(s1,e1),s1++,e1--;
}
bool next_permutation(int* start,int* end){
int *temp1=end-1,*temp2=temp1-1;
while(*temp1<=*temp2&&temp2>=start
4000
) temp2--,temp1--;
if(temp2<start) return false;
for(temp1=end-1;*temp1<=*temp2;temp1--);
swap(temp1,temp2);
reverse(temp2+1,end);
return true;
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++) s[i-1]=i;
for(int i=1;i<m;i++) next_permutation(s,s+n);
for(int i=0;i<n-1;i++) printf("%d ",s[i]);
printf("%d\n",s[n-1]);
}
return 0;
}
相关文章推荐
- HDU1027(next_permutation应用)
- next_permutation的简单应用HDU1207
- HDU 1027 Ignatius and the Princess II(next_permutation()的应用)
- HDU1027 Ignatius and the Princess II 【next_permutation】【DFS】
- poj 1256 Anagram—next_permutation的神奇应用
- HDU 1027 Ignatius and the Princess II 【next_permutation(a,a+n)的应用】
- 排列 next_permutation的应用
- 7.2.1 生成1~n的排列(全排列)【STL__next_permutation()_的应用】
- next_permutation()应用举例
- POJ1833 排列(next_permutation()的应用)
- next_permutation应用
- HDU 1027 STL中next_permutation的应用
- HDU1716 next_permutation 的简单应用 排列2
- HOJ 1191 (next_permutation()的应用)
- POJ1833 & POJ3187 & POJ3785 next_permutation应用
- 【C++ STL应用与实现】62: 如何使用std::next_permutation
- POj-2718 Smallest Difference--全排列next_permutation()的应用文章标题
- HDU1027 Ignatius and the Princess II 【next_permutation】【DFS】
- POJ1833 & POJ3187 & POJ3785 next_permutation应用
- next_permutation在排列类问题中的应用