2018EC Final I. Misunderstood … Missing

题目大意

一个人一开始有攻击力 A 和增量 D ,在每一轮操作开始前攻击力会增加 D ,共有 n(1n100) 轮操作,每轮操作有三个选择 ai,bi,ci1ai,bi,ci109) ,分别为:在该轮攻击,造成 A+ai 伤害;在该轮不攻击,让增量 D 增加 bi ;在该轮不攻击,让攻击力 A 增加 ci 。求完成 n 轮操作后,总共造成伤害的最大值是多少。

思路

我们考虑每个操作对于结果会产生什么影响,在第 i 轮中,设在本轮操作后的所有 j 次攻击,每个攻击所在的轮次为 dx ,对于第一种操作,对于答案所产生的贡献就为 ai ;对于第二种操作,那么这次操作对于总攻击力产生的贡献就为 bi(x=1tdxmj) ;对于第三种操作,其对总攻击力产生的贡献为 cij 。于是我们可以考虑从后往前 dp ,设 f[i,j,k] 为从第 i 轮往后,攻击力 j 次,攻击所在的回合数的和 x=1tdxk 时,对答案产生贡献的最大值。于是根据上面的分析,有如下转移:

f[i,j,k]=max{f[i,j,k],f[i+1,j,k]+cij,f[i+1][j][k],f[i+1,j,k]+bi(kj+1)}

f[i,j+1,k+i]=max{f[i,j+1,k+i],f[i,j,k]+ai}

初始值为 f[n,1,n]=an ,转移时注意 k 的枚举范围为 [(j+1+j+i1)j2,(nj+1+n)j2]来排除非法状态,此外由于数组过大,通过滚动数组的方式优化掉第一维,复杂度 O(n4)

代码

#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 long double eps = 1e-10;
const long double pi = acos(-1.0);
const LL MOD = 100000000;
const LL mod = 998244353;
const int maxn = 100010;

LL dp[2][105][5055];
int T, N;
LL a[maxn], b[maxn], c[maxn];

void solve()
{
	LL ans = 0;
	dp[N & 1][1][N] = a[N];
	for (LL i = N - 1; i >= 1; i--)
	{
		for (LL j = N - i; j >= 1; j--)
		{
			LL up = (N - j + 1 + N) * j / 2, down = (i + i + j) * j / 2;
			for (LL k = up; k >= down; k--)
			{
				dp[i & 1][j][k] = max(dp[i & 1][j][k], dp[(i + 1) & 1][j][k] + c[i] * j);
				dp[i & 1][j + 1][k + i] = max(dp[i & 1][j + 1][k + i], dp[(i + 1) & 1][j][k] + a[i]);
				dp[i & 1][j][k] = max(dp[i & 1][j][k], dp[(i + 1) & 1][j][k] + b[i] * (k - j * i));
			}
		}
	}
	for (int j = 0; j <= N; j++)
	{
		for (int k = 0; k <= (N + 1) * N / 2; k++)
			ans = max(ans, dp[1][j][k]);
	}
	cout << ans << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> N;
		for (int i = 0; i <= N; i++)
		{
			for (int j = 0; j <= N * (N + 1) / 2; j++)
				dp[0][i][j] = dp[1][i][j] = 0;
		}
		for (int i = 1; i <= N; i++)
			cin >> a[i] >> b[i] >> c[i];
		solve();
	}

	return 0;
}
``
posted @   Prgl  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示