Official

D - プレゼンテーションの発表順 / Presentation Order Editorial by MMNMM


\(N!\) 通りのすべての発表順を探索し、\(M\) 個の制約条件をすべて満たしているかと、総合スコアを計算することでこの問題を解くことができます。

時間計算量は \(O((N+M)N!)\) となり、この問題の制約のもと十分高速です。

実装例は以下のようになります。 順列の全探索については、C++ では std::next_permutation が、Python では itertools.permutations が便利です。 再帰関数を使って実装することもできるので、好きな実装方針に慣れておくとよいでしょう。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int N, M;
    cin >> N >> M;

    vector<int> A(N);
    for (int& a : A) {
        cin >> a;
    }

    vector<pair<int, int>> constraint(M);
    for (auto& [u, v] : constraint) {
        cin >> u >> v;
        --u;
        --v;
    }

    int ans = 0;

    // 発表順を全探索する
    vector<int> order(N);
    for (int i = 0; i < N; ++i) {
        order[i] = i;
    }
    do {
        // 制約条件をすべて満たしているか判定する
        bool ok = true;
        for (auto [u, v] : constraint) {
            if (order[u] > order[v]) { // 満たしていないものがあれば
                ok = false; // NG
            }
        }
        if (!ok) continue; // 満たしていないものがあればスコアを計算しない
        
        // スコアを計算
        int now = 0;
        for (int i = 0; i < N; ++i) {
            now += (order[i] + 1) * A[i];
        }
        ans = max(ans, now); // 最大値を更新
    } while (ranges::next_permutation(order).found);

    cout << ans << endl;
    return 0;
}
from itertools import permutations


N, M = map(int, input().split())
A = list(map(int, input().split()))

constraint = []
for i in range(M):
    u, v = map(int, input().split())
    constraint.append((u - 1, v - 1))

ans = 0
for order in permutations(range(N)):
    # 制約条件をすべて満たしているか判定する
    ok = True
    for u, v in constraint:
        if order[u] > order[v]: # 満たしていないものがあれば
            ok = False # NG
    if not ok:
        continue # 満たしていないものがあればスコアを計算しない

    # スコアを計算
    ans = max(ans, sum((o + 1) * a for o, a in zip(order, A))) # 最大値を更新

print(ans)

posted:
last update: