2-3 排列还原 (25 分)
牛牛的作业簿上有一个长度为n的排列A[1...n],这个排列包含了从1到n的n个数,但是因为某种原因,其中有一些位置(不超过10个)看不清了,但是牛牛记得这个排列的顺序对的数量是k,顺序对是指满足i<j且A[i]<A[j]的对数。请帮助牛牛计算出符合要求的排列数目。输入n,k与序列A,返回可能的存在排列数目。
输入格式:
输入的第一行包含两个整数n和k(1≤n≤100,1≤k≤n(n−1)/2),接下来的一行,包含n个数字表示排列A,其中等于0的项表示看不清的位置(不超过10个)。
输出格式:
输出一行表示合法排列的数目。
输入样例:
5 5
4 0 0 2 0
输出样例:
2
代码如下:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
//数一数顺序对一共多少个
int countDui(vector<int>li) {
int count = 0;
for (int i = 0; i < li.size(); i++) {
for (int j = i+1; j < li.size(); j++) {
if (li[i] < li[j]) count++;
}
}
return count;
}
int main() {
int sum = 0; //记录多少种可能性
int n, k;
cin >> n >> k;
int tt;
vector<int> a;
vector<int>t;
for (int i = 0; i < n; i++) {
cin >> tt;
a.push_back(tt);
}
for (int i = 1; i <= n; i++) {
if (find(a.begin(), a.end(),i) == a.end()) {
t.push_back(i);//将看不见的数字放入t 在下一步排列组合所有情况
}
}
do {
vector<int>ab(a);
int cnt = 0;
for (int i = 0; i < t.size(); i++) {
while (1) {
if (ab[cnt] == 0) {
ab[cnt] = t[i]; //将所有的排列组合放入放入原数组,看顺序对是否相等 相等即为一种可能性
break;
}
cnt++;
}
}
if (countDui(ab) == k) sum++;
} while (next_permutation(t.begin(), t.end()));
cout << sum << endl;
return 0;
}