遇到这个算法是在大牛写的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的更多相关文章

  1. stl算法:next_permutation剖析

    在标准库算法中,next_permutation应用在数列操作上比较广泛.这个函数可以计算一组数据的全排列.但是怎么用,原理如何,我做了简单的剖析. 首先查看stl中相关信息.函数原型: templa ...

  2. generating permunation——全排列(算法汇总)

    本文一共提供了4种全排列的方法,包括递归非字典序版本.递归字典序版本.标准库版本和BFS字典序版本,当然BFS非字典序实现相对于BFS字典序版本更加简洁,稍加修改即可. 说明:递归版本基于网上现有代码 ...

  3. 编程艺术第十六~第二十章:全排列/跳台阶/奇偶调序,及一致性Hash算法

    目录(?)[+]   第十六~第二十章:全排列,跳台阶,奇偶排序,第一个只出现一次等问题 作者:July.2011.10.16.出处:http://blog.csdn.net/v_JULY_v. 引言 ...

  4. 2.1.12 Next Permutation 下一个字典序数组

    对当前排列从后向前扫描,找到一对为升序的相邻元素,记为i和j(i < j).如果不存在这样一对为升序的相邻元素,则所有排列均已找到,算法结束:否则,重新对当前排列从后向前扫描,找到第一个大于i的 ...

  5. generating permunation

    generating permunation——全排列(算法汇总) #include <iostream> #include <string> #include <vec ...

  6. 全排列问题(递归&非递归&STL函数)

    问题描述: 打印输出1-9的所有全排序列,或者打印输出a-d的全排列. 思路分析: 将每个元素放到余下n-1个元素组成的队列最前方,然后对剩余元素进行全排列,依次递归下去. 比如:1 2 3 为例首先 ...

  7. LeetCode(31) Next Permutation

    题目 Implement next permutation, which rearranges numbers into the lexicographically next greater perm ...

  8. LeetCode(60) Permutation Sequence

    题目 The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of th ...

  9. 【04NOIP普及组】火星人(信息学奥赛一本通 1929)(洛谷 1088)

    [题目描述] 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类 ...

随机推荐

  1. Groovy系列(1)- Groovy简述

    Groovy简述 前言 由于性能测试的JSR223 Sampler取样器需要用到 Groovy 语言,这两天对其进行了粗略的学习,本文是对学习做的一个简单总结,主要内容参考于官方文档(Groovy 的 ...

  2. web 阶段的一些简答题

    1.jsp 9个隐含对象 2. jsp 4大域对象 3.mybatis 中 #{} %{ } 的区别于联系 4. Servlet容器默认是采用单实例多线程的方式处理多个请求的: 5.Cookie 与S ...

  3. 鸿蒙内核源码分析(位图管理篇) | 谁能一分钱分两半用 | 百篇博客分析OpenHarmony源码 | v19.03

    百篇博客系列篇.本篇为: v19.xx 鸿蒙内核源码分析(位图管理篇) | 谁能一分钱分两半用 | 51.c.h .o 先看四个宏定义,进程和线程(线程就是任务)最高和最低优先级定义,[0,31]区间 ...

  4. 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核资源 | 百篇博客分析OpenHarmonyOS | v2.07

    百篇博客系列篇.本篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核资源 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核 ...

  5. CF5E-Bindian Signalizing【单调栈】

    正题 题目链接:https://www.luogu.com.cn/problem/CF5E 题目大意 圆上有\(n\)个山,两个山之间可以看到当且仅当它们之间的两条弧中有一条满足所有山都不高于它们两个 ...

  6. P5934-[清华集训2012]最小生成树【最小割】

    正题 题目链接:https://www.luogu.com.cn/problem/P5934 题目大意 给出\(n\)个点\(m\)条边的一张图,再加入一条边\((u,v,L)\)求至少删掉多少条边可 ...

  7. 基于Processing图像序列处理保存导出的流程梳理

    做一个基于processing的图像序列处理保存导出的流程梳理.本案例没有什么实质性的目的,仅为流程梳理做演示. 准备 把需要处理的影像渲染成序列图片,可以在PR中剪辑并导出PNG序列[格式倒是没什么 ...

  8. 关于mysql基础

    早就想把自己的数据库基础巩固一下,然而一直没有时间,今天终于抽出时间对mysql数据库基础进行了学习与扩展. mysql与其他数据库的区别 Sqlite: 开源免费,体积小,单文件,没有进程.磁盘读性 ...

  9. mysql面试题及答案,mysql最新面试题,mysql面试题大全汇总

    mysql最新面试题及答案汇总 Mysql 的存储引擎,myisam和innodb的区别.mysql最新面试题 答: 1.MyISAM 是非事务的存储引擎,适合用于频繁查询的应用.表锁,不会出现死锁, ...

  10. SPA测试

    1.生产端:环境准备为了进行SPA测试,在生产数据库中创建了SPA测试专用用户,避免与其他用户相互混淆与可能产生的误操作. CREATE USER SPA IDENTIFIED BY SPA DEFA ...