擅长排列的小明STL
排列组合的题目 分为两种解法:递归解法 非递归解法
其中 最容易的在本人看来就是非递归解法中的字典序 在C++中有一个函数是next_permutation(str.begin(),str.end());
使用它可以轻松全排列一个字符串 如果是无序字符串求全排列 一般都会对字符串进行sort排序 但本题是有序的 所以不需要用到sort
主要是大家一定要会用next_permutation(str.begin(),str.end());这个函数 最好的方法就是自己测试调试 下面我会给出测试代码
大家可以自己来调一下 以便迅速上手 不要看到这个函数就怕了 其实很简单 自己调一调就懂了
如果存在str之后的排列,就返回true。如果str是最后一个排列没有后继,返回false,每执行一次,str就变成它的后继
#include <iostream> #include <algorithm> #include <string.h> using namespace std; int main() { string str; cin>>str; while(next_permutation(str.begin(),str.end())) { cout<<str<<endl; } }还有不了解字典序是什么或者是全排列是什么的童鞋看这里:http://blog.****.net/laojiu_/article/details/51115352
我这里打博客主要是为了的总结方便复习~
那么这道题其实非常简单 连n个数的全排列都能求出来 那么在n个中取m个不是更加简单么 只需要输出n全排列的前m个数就好了啊
唯一需要注意的就是不要重复就好了 这里可以用set 但是其实再创一个字符串 判是否相等 不等输出就好了
用C语言如何解决呢
第一步:先从一个排列的最后一位p[n]向前找 找到 第一个递减的位置 p[i-1]<p[i] 记录下i-1的位置
第二步:从位置i开始向后找 找到最后一个大于p[i-1]的数 并记录下表为key
第三步:交换i-1和key位置的元素
第四步:反转i-1位置之后的所有元素
以上四步做完即得到了str的下一个排列 如 132 的下一个排列
第一步:记录i-1的位置为0 因为13 是从右边找第一个递减的位置 1<3
第二步:找到最后一个大于i-1位置的数为2并记录它的下标key=2
第三步:将i-1位置 和key位置的值交换 得到231
第四步:将i-1位置之后的元素翻转 也就是将0位置之后的元素翻转 得到132的下一个排列为213
如果以上都看懂了 那么这道题就很好解出来了 并且以后碰到排列的题 几乎都可以用到以上这些方式
有了next_permutation()妈妈再也不用担心我A不出题了~
直接上代码
哦 还有非常重要的一点忘记说了 在算法竞赛中 一旦用到排列组合 记得用C来写输入输出
如果用C++来写cin cout很容易超时 交题的话要交C++而不交G++今天刷另一道题的惨痛教训
#include <iostream> #include <algorithm> #include <set> #include <cstdio> #include <cstdlib> #include <string.h> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { int n,m; char ch; string s1,s2=" "; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { ch='0'+i; s1+=ch; } do { if(s2!=s1.substr(0,m)) cout<<s1.substr(0,m)<<endl; s2=s1.substr(0,m); }while(next_permutation(s1.begin(),s1.end())); } }