您的位置:首页 > 其它

next_permutation全排列

2016-08-03 17:04 211 查看
有一个长度为n的排列A,这个排列包含了从1到n的n个数,但有一些数字先用0代替

在这个数列中顺序对的数量是K个,顺序对的是指当i<j时,A[i]<A[j],求符合这个要求的序列的个数

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> v;
vector<int> vv;
vector<vector<int>> ret;
int sumunknow(int n)
{
//n!
int count = 1;
for (int i = 1; i <= n; ++i){
count *= i;
}
return count;
}

int main()
{
int n, k;
int x;
int unknow = 0;
int count;
while (cin >> n >> k){
//找出所有看不清的数字放到v中
for (int i = 0; i < n; ++i){
cin >>x;
v.push_back(x);
if (x == 0)
++unknow;
}
count = sumunknow(unknow);//有count种可能的排列(unknow的阶层)

for (int i = 1; i <= n; ++i){//i为从1~n的数
int j = 0;
for (; j < v.size(); ++j){
if (v[j] == i)//i这个数已经存在,即能看清的数,跳出执行下一次循环
break;
}
if (j == v.size())
vv.push_back(i);//存放的是看不清的那几个数,且这些数是升序存放的
}

int needpushcount=0;
while (needpushcount<count){
next_permutation(vv.begin(), vv.end());
int k = 0;
vector<int> subret;
for (int i = 0; i < v.size(); ++i){
if (v[i] != 0){
subret.push_back(v[i]);
}
else{
subret.push_back(vv[k++]);
}
}
ret.push_back(subret);
++needpushcount;
//NextPermutation(vv.begin(),vv.end());//自己模拟的库函数,必须放在此处,不能放在前面,因为实现的功能暂不支持
}

int result = 0;
int sum = 0;
for (int i = 0; i < count; ++i){
for (int j = 0; j < v.size(); ++j){
for (int k = 1; k < v.size()-j; ++k){
if (ret[i][j] < ret[i][j + k])
++sum;
}
}
if (sum == k)//***
++result;
sum = 0;
}
cout << result<<endl;
}

return 0;
}


next_permutation()这个函数是C++的一个函数

内部实现原理:
如果要比较的数列中只有一个元素的话返回直接false;否则使变量__i指数列的最后一个元素,进入循环 ;从最右边边开始比较俩个相邻的元素,直到找到左边比右边小的那两个数,左边那个就是待交换的数
再从最右边开始,找比代替换的那个数大的第一个元素,然后交换这两个数,交换之后反转被替换元素之后的所有元素

自己实现了一个NextPermutation(),只针对数据是int类型的操作
bool NextPermutation(vector<int>::iterator first,vector<int>::iterator last)
{
vector<int>::iterator tmp = last;
if (first == last || first == --tmp)
return false;
tmp = last;
vector<int>::iterator  Rnum = --tmp;
vector<int>::iterator  Lnum = --tmp;
while (Lnum >= first){
if (*Lnum < *Rnum){
vector<int>::iterator  fromlast = last-1;
while (1){
if (*fromlast > *Lnum){
swap(*fromlast, *Lnum);
reverse(Lnum+1,last);
return true;
}
--fromlast;
}
}
else{
if (Lnum != first){
--Lnum;
--Rnum;
}
else
return false;
}
}
return false;
}


使用这个函数的时候一定要先升序排列,我的这篇博客有详解:
http://lingdandan.blog.51cto.com/10697032/1773352

《完》
本文出自 “零蛋蛋” 博客,谢绝转载!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: