这道题就是一个全排列问题,可以用dfs中的全排列型递归做。
思路:首先我们知道,我们需要列举出n个数的全排列方案,并且我们从题目中可以知道,火星人的数字是根据全排列的字典序的顺序进行定义数字的,我们只需要知道在火星人列举出的数组属于字典序中的第几个,然后再加上m,得出当前字典序加上m的方案就行了。
所以我们选择用全排列的递归模板解题,这里可以不要用二维数组存储,因为n<=10000,这样会导致数组越界,所以我们需要想办法优化一下,这时我们想到用dfs中进行输出就行了。所以不用定义二维数组,这跟上一个题是不一样的。
写出来之后,我们需要注意的有两点:
1.当我们判断终止条件的时候需要进行剪枝,因为这里的n很大,当我们已经找到那个唯一的方案数之后终止dfs的搜索就行了,所以我们需要一个标志变量flag,当我们找到这个方案的时候就直接将它变为true,然后就会终止查找;
2.当我们没有生成方案的时候,我们的数组初始是怎样的我们并不知道,因为在我们通常的思路里,没有生成方案之前就全是0,但是,这里的题目有一个要求,就是我们需要按火星人给的这一组数字进行搜索判断,然后再生成方案,这一点需要额外注意!
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 10010
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
int n, m, counts;
LL arr[MAX];
LL st[MAX];
LL nono[MAX];
LL heihei;
bool flag = false;
void dfs(LL u) {
if (flag)
return;//剪枝
if (u > n) {
heihei++;
if (heihei == m + 1) {
flag = true;
for (int i = 1; i <= n; i++) {
cout << arr[i] << " ";
}
}
return;
}
for (LL i = 1; i <= n; i++) {
if (!heihei) {
i = nono[u];
}
if (!st[i]) {
st[i] = 1;
arr[u] = i;
dfs(u + 1);
st[i] = 0;
arr[u] = 0;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> m;
for (LL i = 1; i <= n; i++)
cin >> nono[i];
dfs(1);
return 0;
}