有一个长度为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类型的操作
#include <iostream> using namespace std; void Reverse(int* start, int* end) { --end; while (start < end){ swap(*start, *end); ++start; --end; } } //[)前闭后开 且此函数只处理int类型的数据 bool MyNextPermutation(int first,int last,int* arr) { if (first >= last || first + 1 == last) return false; int i = last - 1; int ii = i; --i; while (i >= 0 && arr[i] >= arr[ii]){ --i; --ii; } if (i < 0) return false; int j = last - 1; while (arr[j] <= arr[i]) --j; swap(arr[i],arr[j]); Reverse(&arr[ii],&arr[last-1]+1); return true; } int main() { int arr[] = { 1, 2, 3, 4 }; //int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; bool ret = true; while (ret){ cout << arr[0] << arr[1] << arr[2] << arr[3] << endl; /*cout << arr[0] << arr[1] << arr[2] << arr[3] <<\ arr[4] << arr[5] << arr[6] << arr[7] << endl;*/ ret=MyNextPermutation(0,sizeof(arr)/sizeof(arr[0]),arr); } system("pause"); return 0; }
使用这个函数的时候一定要先升序排列,我的这篇博客有详解:
http://lingdandan.blog.51cto.com/10697032/1773352
《完》