九度 1120
-
题目描述:
-
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。
-
输入:
-
输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
-
输出:
-
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:
已知S = s1s2...sk , T = t1t2...tk,则S < T 等价于,存在p (1 <= p <= k),使得
s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。
-
样例输入:
-
abc
-
样例输出:
-
abc acb bac bca cab cba
这题我新接触到了一个全排列函数,是STL的库函数,next_permutation(),有了这个函数全排列问题就变得非常简单了,具体代码如下:#include <iostream> #include <cstring> #include<stdio.h> #include <algorithm> using namespace std; int main() { char s[7]; while (scanf("%s",s)!=EOF) { printf("%s\n",s); while (next_permutation(s,s+strlen(s))) printf("%s\n",s); printf("\n"); } return 0; }
关于全排列函数的相关知识:
next_permutation是STL中专门用于排列的函数,运行需要包含头文件
#include <algorithm>
using namespace std
next_permutation(start,end)
注意:函数要求输入的是一个升序排列的序列的头指针和尾指针
如果输入的是一个数组例如:
double a[5]
则:
double *start = &a[0];
double *end = &a[5];(实际上数组的最有一个元素应该是a[4],也就是说
end实际指向的应该是数组最有一个元素指针对下
一个指针)end = start+N;
函数输入之所以要求必须是一个升序的排列,原因在于函数运行一次对输入的数组进行移动排列一次后,在函数退出前判断移动后的数组是否升序,如果升序则函数 返回BOOL变量false,否则返回true。 这样当你输入的是一个升序的排列后,每运行一次函数就对数组进行一次移动得到一个新的排列,函数对数组的移动排列采用递归方式。当所有排列方式都遍历一遍 后函数最后一次输出的又是一个升序的排列,也就是和你最先输入的数组一样的排列。
因此你可以用下面结构遍历所有的排列可能:
while ( next_permutation(start,end))//判断是否函数返回true,是责继
//续循环,否则推出说明排列完毕
{
//你要做的处理程序放在此循环内copy(start,end, ostream_iterator<int>(cout, "\n"));
cout<<endl:
........
.......
}//排序可以用sort()实现
首先,给出算法的思路
设R={r1,r2,...,rn}是要进行排列的n个元素,Ri=R-{ri}。
集合X中元素的全排列记为permutation(X),(ri)permutation(X)表示在全排列permutation(X)的每一个排列前加上前缀ri得到的排列。
R的全排列可归纳定义如下:
当n=1时,permutation(R)={r},r是集合R中唯一的元素;
当n>1时,permutation(R)由(r1)permutation(R1),(r2)permutation(R2),……,(rn)permutation(Rn)构成。
此算法要求待排列的数据是互异的,因为该算法不能检测同种排列是否已经输出,如:
1, 1, 2
那么,全排列期望输出是:
1, 1, 2
1, 2, 1
2, 1, 1
但是该算法的输出:
1, 1, 2
1, 2, 1
2, 1, 1
1, 1, 2
1, 2, 1
2, 1, 1
这是该算法的缺点,也限制了它的适用范围。http://hi.baidu.com/%B0%AE%D0%C4%CD%AC%C3%CB_%B3%C2%F6%CE/blog/item/566a4d35a31ce61990ef39b6.html