[CodeForces1487E] Cheap Dinner
Link:https://codeforces.com/problemset/problem/1487/E
description:
\(4\) kinds of dishes, each has \(n_i\) courses for \(i\in \{1,2,3,4\}\), we have to choose a minimum cost to cover all of the \(4\) kinds, (exactly \(4\) dishes).
solution:
Let dp[i][j] be a of the min_cost cover the \(1\) to \(ith\) kinds, ending with the course \(j\) in kind \(i\)
The transition equation is :
\(dp[i][j] = min\{dp[i - 1][j]\ |\ dp[i - 1][j] is\ available\} + p[i][j]\)
How to known whether a dish is available to choose?
Use a data structure: mutiset(RBTree), with which we can find the minimum and delete the contradictory \(dp[i-1][j]\).
Use \(3\) graphs to mark the conflictions between \(1,2;2,3;and 3,4\).
code:(reference:BledDest)
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
const int inf(1e9);
int main() {
vector<int> n(4);
for (int i = 0; i < 4; ++i)
scanf("%d", &n[i]);
vector<vector<int>> p(4);
for (int i = 0; i < 4; ++i) {
p[i].resize(n[i]);
for (int j = 0; j < n[i]; ++j)
scanf("%d", &p[i][j]);
}
vector<vector<vector<int>>> ctr(3);
for (int i = 0; i < 3; ++i) {
ctr[i].resize(n[i]);
int m;
scanf("%d", &m);
while(m--) {
int x, y;
scanf("%d%d", &x, &y);
--x, --y;
ctr[i][y].push_back(x);
}
}
vector<vector<int>>dp(4);
dp[0] = p[0];
for (int i = 1; i < 4; ++i) {
dp[i].resize(n[i]);
multiset<int> s;
for (int j = 0; j < n[i - 1]; ++j)
s.insert(dp[i - 1][j]);
for (int j = 0; j < n[i]; ++j) {
for (auto& k : ctr[i - 1][j])
s.erase(s.find(dp[i - 1][k]));
if (s.empty())dp[i][j] = inf;
else dp[i][j] = *s.begin() + p[i][j];
for (auto& k : ctr[i - 1][j])
s.insert(dp[i - 1][k]);
}
}
int ans = *min_element(dp[3].begin(), dp[3].end());
printf("%d", ans != inf ? ans : -1);
}