[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);
}
posted @ 2021-02-25 18:49  _dwt  阅读(52)  评论(0)    收藏  举报