2016CCPC Final I. Mr. Panda and Crystal

2022/3/9 23:19:55

本文主要是介绍2016CCPC Final I. Mr. Panda and Crystal,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目大意

总共有魔力值 \(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;
}


这篇关于2016CCPC Final I. Mr. Panda and Crystal的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程