练习到全排列系列的问题,回溯法之类的方法都可以解决。但是在STL中有一个next_permutation函数,可以非常简单便捷地实现全排列功能。
next_permutation函数的实现是将一个数据组合转化成它的下一个字母序稍大的组合,当数据组合为递减组合时返回0。在此简述该函数执行原理:对一个排列组合求它的下一个排列组合时,首先找到一组相邻的i和ii数,且a[i]<a[ii],再从末尾开始找到第一个大于a[i]的数,记其下标为j,j可与ii下标重合,交换i和j下标所指向元素,将a[ii]下标后的元素颠倒顺序,包括a[ii]。举例:1 5 2 4 3 找到第一组相邻的符合要求的数 i 2 ii 4 自末尾找到第一个大于i下标指向的数 此时j为3 交换i 和j 下标指向数 此时排列组合为 15 3 4 2 最终将ii下标往后的元素颠序 最终生成组合 1 5 3 2 4
使用next_permutation很容易地AC了几道全排列系列的题目。给出AC代码:
POJ 1833:
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=1030;
int a[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
/* do
{
for(int i=0; i<n; i++)
printf("%d%c",a[i],i==n-1?'\n':' ');
} //打印全排列
while(next_permutation(a,a+n));*/
for(int i=0; i<k; i++)
next_permutation(a,a+n);
for(int i=0; i<n; i++)
printf("%d%c",a[i],i==n-1?'\n':' ');
}
return 0;
}
//next_permutation 当数组为递减顺序排列时返回 flase
//所以如果需要输出全排列时 需要事先排成升序
//该题 求的是往后之后的第k个序列 执行k次函数即可 不需要 顾忌返回值
//perv_permutation 函数相同原理
POJ 1146:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=55;
char a[maxn];
int main()
{
while(scanf("%s",a)&&strcmp(a,"#"))
{
int len=strlen(a);
if(next_permutation(a,a+len))
printf("%s\n",a);
else
printf("No Successor\n");
}
}
POJ 1256 需要注意根据题目要求自定义cmp函数
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<ctype.h>
using namespace std;
const int maxn=15;
char a[maxn];
int cmp(char a,char b)
{ //定义大小
if(islower(a)&&islower(b))
return a<b;
if(isupper(a)&&isupper(b))
return a<b;
if(islower(a)&&isupper(b))//a小写 b大写
{
if(a-32==b) //如果此时是 a 和A 的情况
return 0;
else
return a-32<b;
}
if(isupper(a)&&islower(b))//a 大写 b小写
{
if(a==b-32)
return 1;
else
return a<b-32;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
int len=strlen(a);
sort(a,a+len,cmp);
do
{
printf("%s\n",a);
}
while(next_permutation(a,a+len,cmp));
}
return 0;
}
STL库有很多便捷高效的算法,待探索。
特记下,以备后日回顾。