您的位置:首页 > 其它

擅长排列的小明STL

2017-03-04 19:16 183 查看
排列组合的题目 分为两种解法:递归解法 非递归解法

其中 最容易的在本人看来就是非递归解法中的字典序 在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.csdn.net/laojiu_/article/details/51115352

我这里打博客主要是为了的总结方便复习~

那么这道题其实非常简单 连n个数的全排列都能求出来 那么在n个中取m个不是更加简单么 只需要输出n全排列的前m个数就好了啊

唯一需要注意的就是不要重复就好了 这里可以用set 但是其实再创一个字符串 判是否相等 不等输出就好了 

用C语言如何解决呢

第一步:先从一个排列的最后一位p
向前找 找到 第一个递减的位置 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()));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: