2018EC Final I. Misunderstood … Missing
题目大意
一个人一开始有攻击力 \(A\) 和增量 \(D\) ,在每一轮操作开始前攻击力会增加 \(D\) ,共有 \(n(1\leq n\leq 100)\) 轮操作,每轮操作有三个选择 \(a_{i},b_{i},c_{i}(1\leq a_{i},b_{i},c_{i}\leq 10^9)\) ,分别为:在该轮攻击,造成 \(A+a_{i}\) 伤害;在该轮不攻击,让增量 \(D\) 增加 \(b_{i}\) ;在该轮不攻击,让攻击力 \(A\) 增加 \(c_{i}\) 。求完成 \(n\) 轮操作后,总共造成伤害的最大值是多少。
思路
我们考虑每个操作对于结果会产生什么影响,在第 \(i\) 轮中,设在本轮操作后的所有 \(j\) 次攻击,每个攻击所在的轮次为 \(d_{x}\) ,对于第一种操作,对于答案所产生的贡献就为 \(a_{i}\) ;对于第二种操作,那么这次操作对于总攻击力产生的贡献就为 \(b_{i}(\sum_{x=1}^{t}d_{x}-mj)\) ;对于第三种操作,其对总攻击力产生的贡献为 \(c_{i}j\) 。于是我们可以考虑从后往前 \(dp\) ,设 \(f[i,j,k]\) 为从第 \(i\) 轮往后,攻击力 \(j\) 次,攻击所在的回合数的和 \(\sum_{x=1}^{t}d_{x}\) 为 \(k\) 时,对答案产生贡献的最大值。于是根据上面的分析,有如下转移:
\[f[i,j,k]=max\{f[i,j,k],f[i+1,j,k]+c_{i}j,f[i+1][j][k],f[i+1,j,k]+b_{i}(k-j+1)\}
\]
\[f[i,j+1,k+i]=max\{f[i,j+1,k+i],f[i,j,k]+a_{i}\}
\]
初始值为 \(f[n,1,n]=a_{n}\) ,转移时注意 \(k\) 的枚举范围为 \([\frac{(j+1+j+i-1)j}{2},\frac{(n-j+1+n)j}{2}]\)来排除非法状态,此外由于数组过大,通过滚动数组的方式优化掉第一维,复杂度 \(O(n^4)\) 。
代码
#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;
}
``

浙公网安备 33010602011771号