Permutations 题解

发布时间 2023-08-05 19:01:16作者: xvl

题目传送门

一道枚举题。

数据范围非常小,考虑暴力枚举全排列。

可以 dfs 两次,第一次求出能使 \(f(p)\) 取得的最大值。第二次求出第 \(m\) 个排列。

注意一下,第二次 dfs 的时候需要按字典序枚举。

Code

#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;
}