专栏文章

2025/5/17 模拟赛 T4 题解

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipa2nlk
此快照首次捕获于
2025/12/03 08:37
3 个月前
此快照最后确认于
2025/12/03 08:37
3 个月前
查看原文

题解

题面描述

nn 种物体,每种物体有 aabb 两个属性,数量无穷多,且物体单价只与 ba\frac{b}{a} 有关,若 ba\frac{b}{a} 不降,则物体单价不降,且物体间可无限合并,问 aa 不大于 mm 时物体的总价最大为多少。

sol

若随意合并,则合并后可产生的物体过多,无法处理。所以我们需要想办法让可更新答案的物体在一个可以接受的范围内。不难发现只有 mam \ge a 的物体可以更新答案,且所有物体均有无穷多个,所以我们可以记录不同 aa 时最大的价值是多少,以此更新答案,因为价值关于 bb 存在单调性,所以记录最大的价值可通过记录 bb 实现,这个东西很容易通过完全背包求出,时间复杂度 O(m2)O(m^2)。最后对这 mm 种物体做完全背包即可,时间复杂度 O(m2)O(m^2)

CODE

CPP
#include<bits/stdc++.h>
using namespace std;
int n, m, v[10], val[3005], ans[3005];
int main() {
//	freopen("stone.in", "r", stdin);
//	freopen("stone.out", "w", stdout);
	int t;
	scanf("%d", &t);
	while(t--) {
		memset(val, -0x3f, sizeof(val)), memset(ans, 0, sizeof(ans));
		for(int i = 0; i < 10; ++i) scanf("%d", v + i);
		scanf("%d%d", &n, &m);
		for(int i = n; i; --i) {
			int a, b;
			scanf("%d%d", &a, &b);
			val[a] = max(val[a], b);
		}
		for(int i = 1; i <= m; ++i) 
			for(int j = 1; i + j <= m && j <= i; ++j) 
				val[i + j] = max(val[i + j], val[i] + val[j]);
		for(int i = m; i; --i) {
			if(val[i] > 0) {
				int now = (val[i] * 10 - 1) / i;
				for(int j = 0; j + i <= m; ++j) ans[i + j] = max(ans[i + j], ans[j] + i * v[now]);
			}
		}
		printf("%d\n", ans[m]);
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...