c++ 算法 next_permutation
遇到这个算法是在大牛写的10行的8皇后问题中,下面首先给出这个10行就解决了8皇后的NB代码,我目前还是没有看懂对于皇后不在同一列的判断,因为他巧妙的用了移位操作。
#include<iostream>
#include<algorithm>
#include<bitset>
#include<numeric>
#include<utility>
int main() {
int i = 0;
for (int queens[] = {0,1,2,3,4,5,6,7}; std::next_permutation(queens,queens+8);)
if ((std::bitset<15>(std::accumulate(queens,queens+8, std::make_pair(0, 0), [](std::pair<int, int> a, int b){return std::make_pair((1<<(b+a.second))|a.first,a.second+1);}).first).count() == 8) && (std::bitset<15>(std::accumulate(queens, queens+8, std::make_pair(0, 0), [](std::pair<int, int> a, int b){return std::make_pair((1<<(7+b-a.second))|a.first, a.second+1);}).first).count() == 8))
std::cout << ++i << " : " << queens[0] << queens[1] << queens[2] << queens[3] << queens[4] << queens[5] << queens[6] << queens[7] << std::endl;
return 0;
}
在上面的代码中,用next_permutation的原因是可以生成用0~7表示的所有序列。然后我们用if语句判断此时的序列(也就是每一个列序列)是否符合条件,要是符合就输出,否则就跳过,相当于用了打表的方式,列出所有可能的结果再寻找符合条件的。next_permutation的作用就是生成这所有的可能序列。
next_permutation的作用是:生成下一个较大的序列。perv_permutation的作用是生成下一个较小的序列。
以next_permutation举个例子:
我们用(a1 a2 … am)来表示m个数的一种序列。设序列pn=<3 6 4 2>,根据定义可算得下一个序列pn+1=<4 2 3 6>。观察pn可以发现,其子序列<6 4 2>已经为减序,那么这个子序列不可能通过交换元素位置得出更大的序列了,因此必须移动最高位3(即a1)的位置,且要在子序列<6 4 2>中找一个数来取代3的位置。子序列<6 4 2>中6和4都比3大,但6大于4。如果用6去替换3得到的序列一定会大于4替换3得到的序列,因此只能选4。将4和3的位置对调后形成排列<4 6 3 2>。对调后得到的子序列<6 3 2>仍保持减序,即这3个数能够生成的最大的一种序列。而4是第1次作为首位的,需要右边的子序列最小,因此4右边的子序列应为<2 3 6>,这样就得到了正确的一个序列pn+1=<4 2 3 6>。
下面我们用代码验证一下
#include<iostream>
#include<algorithm>
#include<vector>
using std::cout;
using std::cin;
using std::endl;
int main(int argc,char *argv[])
{
int chs[] = {3,6,4,2};
int count = sizeof(chs)/sizeof(*chs);
std::vector<int> vchs(chs,chs+count);
std::next_permutation(vchs.begin(),vchs.end());
for(auto u:vchs) cout << u << " ";cout << endl;
return 0;
}
下面看看它的实现
#include<iostream>
#include<algorithm>
#include<string>
using std::cout;
using std::cin;
using std::endl;
int main(int argc,char *argv[])
{
for(std::string str;cin >> str ;) {
//如果为空,直接结束
if(str.empty()) {
continue;
}
//长度小于等于一的没有子序列
if(str.length() <= 1) {
cout << "No " << endl;
}
std::string::iterator iPivot = str.end(),iNewHead;
//从最后往前找递减序列,直到找到
for(--iPivot;iPivot != str.begin();--iPivot) {
if(*(iPivot-1) <= *iPivot) {
break;
}
}
//如果一直找到开头,就说明此时已经是一个递减的序列,不会再有比它大的序列了
if(iPivot == str.begin()) {
cout << "No" << endl;
}
iPivot--;
//否则从右侧序列中找小于刚才的iPivot序列的
for(iNewHead = iPivot+1;iNewHead != str.end();++iNewHead) {
if(*iNewHead < *iPivot) {
break;
}
}
//然后交换它们的元素
std::iter_swap(iPivot,--iNewHead);
//然后将后面的翻转
std::reverse(iPivot+1,str.end());
cout << str << endl;
}
return 0;
}
c++ 算法 next_permutation的更多相关文章
- stl算法:next_permutation剖析
在标准库算法中,next_permutation应用在数列操作上比较广泛.这个函数可以计算一组数据的全排列.但是怎么用,原理如何,我做了简单的剖析. 首先查看stl中相关信息.函数原型: templa ...
- generating permunation——全排列(算法汇总)
本文一共提供了4种全排列的方法,包括递归非字典序版本.递归字典序版本.标准库版本和BFS字典序版本,当然BFS非字典序实现相对于BFS字典序版本更加简洁,稍加修改即可. 说明:递归版本基于网上现有代码 ...
- 编程艺术第十六~第二十章:全排列/跳台阶/奇偶调序,及一致性Hash算法
目录(?)[+] 第十六~第二十章:全排列,跳台阶,奇偶排序,第一个只出现一次等问题 作者:July.2011.10.16.出处:http://blog.csdn.net/v_JULY_v. 引言 ...
- 2.1.12 Next Permutation 下一个字典序数组
对当前排列从后向前扫描,找到一对为升序的相邻元素,记为i和j(i < j).如果不存在这样一对为升序的相邻元素,则所有排列均已找到,算法结束:否则,重新对当前排列从后向前扫描,找到第一个大于i的 ...
- generating permunation
generating permunation——全排列(算法汇总) #include <iostream> #include <string> #include <vec ...
- 全排列问题(递归&非递归&STL函数)
问题描述: 打印输出1-9的所有全排序列,或者打印输出a-d的全排列. 思路分析: 将每个元素放到余下n-1个元素组成的队列最前方,然后对剩余元素进行全排列,依次递归下去. 比如:1 2 3 为例首先 ...
- LeetCode(31) Next Permutation
题目 Implement next permutation, which rearranges numbers into the lexicographically next greater perm ...
- LeetCode(60) Permutation Sequence
题目 The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of th ...
- 【04NOIP普及组】火星人(信息学奥赛一本通 1929)(洛谷 1088)
[题目描述] 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类 ...
随机推荐
- oracle 基础SQL语句 增删改
一.SQL操作 查询已创建的数据库:SELECT datname FROM pg_database; 创建数据库:CREATE DATABASE wzxdb; 删除数据库:DROP DATABASE ...
- 我是小白,做PPT像流水账,怎么做一份重点突出的PPT?
1.PPT的封面不要只写标题,还要在显眼的位置写上你的核心观点.比如,你之前做的PPT封面标题是<A产品市场前景分析>,现在不妨加上一个副标题<红海市场中需要找到更多本产品卖点> ...
- P4494-[HAOI2018]反色游戏【圆方树】
正题 题目链接:https://www.luogu.com.cn/problem/P4494 题目大意 给出\(n\)个点\(m\)条边的一张无向图,节点有\(0/1\),每条边可以选择是否取反两边的 ...
- 前端规范之JS代码规范(ESLint + Prettier)
代码规范是软件开发领域经久不衰的话题,几乎所有工程师在开发过程中都会遇到或思考过这一问题.而随着前端应用的大型化和复杂化,越来越多的前端团队也开始重视代码规范.同样,前段时间,笔者所在的团队也开展了一 ...
- robot framework使用SeleniumLibrary打开谷歌浏览器无头模式
注:我百度了一圈并没有发现类似的教程 robot framework的seleniumLibrary一般打开浏览器的方式是用关键字 Open Browser 但是,阅读seleniumLibrary ...
- 小米路由器4a千兆版刷openwrt
现在网上搜小米路由器4a千兆版刷机的都是刷的padavan的,很少能找到openwrt的刷机教程. 首先刷openwrt系统的时候要先刷入引导程序breed,网上有一篇帖子写的很详细(https:// ...
- mysql通过logstash同步数据到es
大小写问题很严重 input 1.statement:mysql的连接使用 jdk版本有强要求 2.jdbc_driver_library:jar包的版本有对应要求 3.jdbc_driver_cla ...
- Linux下关于用户账户的几个文件解析
Linux下关于用户账户的几个文件解析 Linux是一个多用户系统,但是对于一个多用户共存的系统中,当然不能够出现用户相互越权等一系列的安全问题,所以如何正确的管理账户成为了Linux系统中至关重要的 ...
- 学习使用Wpf开源的文本编辑器—smithhtmleditor
前言 本文主要介绍使用Wpf文本编辑器--smithhtmleditor. 编辑器使用 首先新建一个项目WpfEditor. 然后到Codeplex下载smithhtmleditor. 下载地址:ht ...
- rocketmq高可用集群部署(RocketMQ-on-DLedger Group)
rocketmq高可用集群部署(RocketMQ-on-DLedger Group) rocketmq部署架构 rocketmq部署架构非常多,都是为了解决一些问题,越来越高可用,越来越复杂. 单ma ...