Official
D - プレゼンテーションの発表順 / Presentation Order Editorial
by
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:
