题目传送门
一道枚举题……
数据范围非常小,考虑暴力枚举全排列。
可以 dfs
两次,第一次求出能使 f(p) 取得的最大值。第二次求出第 m 个排列。
注意一下,第二次 dfs
的时候需要按字典序枚举。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <bits/stdc++.h> #define ll long long #define INF 1e9 using namespace std; int n, m, cnt = 1, maxf = -INF; int res[10]; bool vis[10]; void dfs1(int cur) { if (cur > n) { int sum = 0; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { int minp = INF; for (int k = i; k <= j; k++) minp = min(minp, res[k]); sum += minp; } } maxf = max(maxf, sum); return ; } for (int i = 1; i <= n; i++) { if (vis[i]) continue; vis[i] = 1; res[cur] = i; dfs1(cur + 1); vis[i] = 0; } } void dfs2(int cur) { if (cur > n) { int sum = 0; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { int minp = INF; for (int k = i; k <= j; k++) minp = min(minp, res[k]); sum += minp; } } if (sum == maxf) { if (cnt == m) { for (int i = 1; i <= n; i++) cout << res[i] << " "; exit(0); } cnt++; } return ; } for (int i = 1; i <= n; i++) { if (vis[i]) continue; vis[i] = 1; res[cur] = i; dfs2(cur + 1); vis[i] = 0; } } signed main() { ios :: sync_with_stdio(0); cin >> n >> m; dfs1(1); memset(vis, 0, sizeof(vis)); dfs2(1); return 0; }
|