2016CCPC Final I. Mr. Panda and Crystal
阿新 • • 發佈:2022-03-09
題目大意
總共有魔力值 \(M\) , \(N\) 種水晶, \(K\) 種合成公式,每種水晶還有一個基本資訊:
\(0\space p_{i}\) :該種水晶不能夠由魔力值直接生成,單價為 \(p_{i}\) 。
\(1\space c_{i} \space p_{i}\) :該種水晶可以消耗 \(c_{i}\) 魔力值生成,單價為 \(p_{i}\) 。
每個合成公式的形式為:
\(x_{i}\space y_{i}\space u_{1}\space v_{1}...\) :表示第 \(x_{i}\) 種水晶可以由 \(y_{i}\) 種水晶一起合成,其中第 \(u_{j}\) 種水晶需要 \(v_{j}\)
求所擁有的魔力值可以製造出的最大水晶價值。
思路
我們可以考慮去求出能夠獲取某種水晶所需要花費的最小魔力值,然後做一個完全揹包來求出最後的答案。對於求出最小魔力值的部分,記 \(d[i]\) 為第 \(i\) 種水晶所需的最小魔力值,於是每個公式可以寫成 \(d[x_{i}]=\sum_{j=1}^{y_{i}}v_{j}*d[u_{j}]\) 的形式,我們可以建立一張有向圖,如果水晶 \(u\) 的最小魔力值會對水晶 \(v\) 的最小魔力值通過公式 \(id\) 產生影響,那麼我們就從 \(u\) 到 \(v\) 連一條權值為 \(id\) 的邊,然後我們通過 \(dijkstra\)
程式碼
#include<bits/stdc++.h> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PII; #define all(x) x.begin(),x.end() //#define int LL //#define lc p*2+1 //#define rc p*2+2 #define endl '\n' #define inf 0x3f3f3f3f #define INF 0x3f3f3f3f3f3f3f3f #pragma warning(disable : 4996) #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) const double eps = 1e-8; const LL MOD = 1000000007; const LL mod = 998244353; const int maxn = 210; const int maxk = 210; struct edge { int to, id; }; int T, cnt = 0; int M, N, K; int t[maxn], c[maxn], p[maxn]; int d[maxn]; priority_queue<PII, vector<PII>, greater<PII>>que; vector<edge>G[maxn]; int dp[10010]; vector<PII>eq[maxn]; void add_edge(int from, int to, int cost) { G[from].push_back({ to,cost }); } void dijkstra() { memset(d, inf, sizeof(d)); for (int i = 1; i <= N; i++) { if (t[i]) { d[i] = c[i]; que.push(PII(d[i], i)); } } while (!que.empty()) { PII p = que.top(); que.pop(); int v = p.second; if (d[v] < p.first) continue; for (int i = 0; i < G[v].size(); i++) { edge& e = G[v][i]; int sum = 0; for (int j = 0; j < eq[e.id].size(); j++) { int num = eq[e.id][j].second, ty = eq[e.id][j].first; if (d[ty] == inf) { sum = -1; break; } sum += d[ty] * num; } if (sum != -1 && sum < d[e.to]) { d[e.to] = sum; que.push(PII(d[e.to], e.to)); } } } } void solve() { dijkstra(); for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { if (j >= d[i]) dp[j] = max(dp[j], dp[j - d[i]] + p[i]); } } int ans = 0; for (int i = 0; i <= M; i++) ans = max(ans, dp[i]); cout << "Case #" << cnt << ": " << ans << endl; } int main() { IOS; cin >> T; while (T--) { for (int i = 1; i <= N; i++) G[i].clear(); for (int i = 0; i <= K; i++) eq[i].clear(); for (int i = 0; i <= M; i++) dp[i] = 0; cnt++; cin >> M >> N >> K; for (int i = 1; i <= N; i++) { cin >> t[i]; if (t[i]) cin >> c[i] >> p[i]; else cin >> p[i]; } int x, y, u, v; for (int i = 1; i <= K; i++) { cin >> x >> y; for (int j = 1; j <= y; j++) { cin >> u >> v; eq[i].push_back(PII(u, v)); add_edge(u, x, i); } } solve(); } return 0; }