擅长排列的小明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就变成它的后继
还有不了解字典序是什么或者是全排列是什么的童鞋看这里: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()));
}
}
其中 最容易的在本人看来就是非递归解法中的字典序 在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()));
}
}
相关文章推荐
- nyoj19擅长排列的小明(STL)&&(DFS)
- NYOJ - 19 - 擅长排列的小明(STL - set +全排列)
- (STL) ACM_擅长排列的小明.(补)
- [南阳]-19 擅长排列的小明 [STL/DFS]
- nyoj19擅长排列的小明(DFS或STL)
- 擅长排列的小明 STL
- NYOJ 19 擅长排列的小明 (STL之next_permutation()的使用)
- 擅长排列的小明 DFS()和 STL两种方法
- 擅长排列的小明 string(stl)的应用 + 排列
- NY19 擅长排列的小明 【STL】
- NYOJ 469 擅长排列的小明 II
- nyoj-469--擅长排列的小明 II
- 擅长排列的小明-递归
- 擅长排列的小明
- nyoj19 擅长排列的小明
- nyoj--19--擅长排列的小明(dfs)
- NYOJ 19 擅长排列的小明
- 擅长排列的小明
- NYOJ 469 擅长排列的小明 II
- nyoj 19 擅长排列的小明 【next_permutation() 】