**题目:**https://www.luogu.org/problemnew/show/P1088
题解:
方法一:直接调用next_permutation
#include <bits/stdc++.h>
using namespace std;
int n,m,a[10005];
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
while(m--) next_permutation(a,a+n);
for(int i=0;i<n;i++) cout<<a[i]<<' ';
return 0;
}
方法二:手打next_permutation
算法思想:
1.首先从最尾端开始往前寻找两个相邻元素,令第一元素为i,第二元素为ii,且满足i<ii。
2.找到这样一组相邻元素后,再从最尾端开始往前检验,找出第一个大于i的元素,令为j,将i,j元素对调(swap)。
3.再将ii之后的所有元素颠倒(reverse)排序。
不理解可以自己举个例子动手模拟一下!!!
#include <bits/stdc++.h>
using namespace std;
int b[10001],i,j,k,m,n,t;
void work()
{//一个全排列序列,左边部分趋向升序,右边部分趋向降序
for(int i=1;i<=m;i++)
{
for(j=n-1;j>=1;j--)
if(b[j]<b[j+1])//从后往前搜
break;//找到最后可增加的那一位,也是右边序列最大的
for(k=n;k>=1;k--)
if(b[k]>b[j])//从后往前搜 找到的就是右边部分最小的
break;//找到最小的可增加的数字
swap(b[j],b[k]);//交换
j=j+1;k=n;
while(j<k)
{//右边部分原来趋向升序排列,现在改为降序排列
swap(b[j],b[k]);
j++;k--;
}
}
}
int main()
{
cin>>n>>m;
for(i=1;i<=n;i++)cin>>b[i];
work();
for(i=1;i<=n-1;i++) cout<<b[i]<<' ';
cout<<b[n]<<endl;
return 0;
}