今天来水一期吉利题。
提醒一下,虽然编号很吉利,但内容可不吉利,做好心理准备!!!
题目背景
小 A 和小 B 用实验基地全新的装备进行了一场世纪蒟蒻之战。
题目描述
众所周知,实验基地的武器都是一次性的。现在,小 A 选取了 n 把不同的武器,小 B 也获取了 m 把不同武器。每个人的武器都可以用编号 11 到编号n或m依次表示,他们将会按此顺序逐个使用武器。
实验仓库记录了所有武器的火力。小 A 的第 k 把武器能爆发出 ak 的能量,而小 B 的第 k 把武器能爆发出 bk 的能量。特别的,当小 A 的第 i 把武器与小 B 的第 j 把武器同时使用,会释放di,j 的能量。由于某些不可描述的组合的奇效,a,b,d 都可能小于 00。
当某人第一个使用了武器,战斗就正式开始,记为第 11 秒,直至某人使用完武器后再无人使用武器,记此时为第 t 秒(t 不为输入数据)。也就是说,在第 11 秒和第 t 秒必须有人使用武器,而在 11 至 t 秒内在符合其他条件下,每一秒双方可以选择按顺序使用武器或不使用。
为了避免打死对方,双方都不一定使用完武器。
由于实验基地有发电装置,如果小 A 没有连续使用武器释放能量,而是休息了x 秒,那么祂将会吸收掉 Ax+B (A,B∈N) 的能量。同样,小 B 间隔 y 秒将吸收Cy+D (C,D∈N) 的能量。连续两秒都释放武器间隔时间为 00 秒,以此类推。
为了防止基地被核爆,你需要算出战斗结束后可能释放的最大总能量(可能为负数)。
若对题目细节有疑惑请先读提示内的额外解释。
输入格式
第一行有两个数n 和m。
第二行有 n 个数,第 k 个数字即 ak。
第三行有 m 个数,第 k 个数字即 bk。
接下来 n 行,每行 m 个数字,其中第 i 行第 j 列表示的是 di,j。
最后一行有四个非负整数 A,B,C,D。
输出格式
只有一行,输出一个数字,即最大可能能量。
输入样例1
7 6
1 9 1 9 8 1 0
1 1 4 5 1 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 0 1 0
输出样例1
45
输入样例2
4 4
-2 -2 -2 -2
2 3 4 9
4 -2 0 4
0 0 0 0
-1 0 1 0
0 0 2 0
1 2 1 0
输出样例2
15
说明/提示
-
战斗的开始时间(第 11 秒)为双方某人最先释放出第一个技能的时间,战斗结束时间为双方某人释放出最后一个技能的时间。结束时间不定。
-
技能必须按顺序释放,但不一定需要在战斗中释放完。
-
a,b,d 可以为负数,总计能量可能为负,“吸收能量”指总能量减少Ax+B 或 Cy+D,也就是间隔时总能量一定减少,而且时间越长减少越多。
-
本题 IO 量较大,建议使用合适的读入方式。
样例解释:
样例 1:每个人在 11 到 66 秒依次使用自己的编号为 11 到 66 的武器即可取到最大值。
样例 2:小 B 在 11 到 44 秒依次使用自己的编号为 11 到 44 的武器,小 A 在第 44 秒使用自己的 11 号武器可以取到最大值。其中单个武器释放的能量为 (−2)+(2+3+4+9)=16,武器碰撞释放 =4 单位的能量,小 A 在前 33 秒吸收了 A×3+B=5 单位的能量。
数据范围:
Subtask | n≤ | m≤ | 分值 |
---|---|---|---|
11 | 1010 | 1010 | 2020 |
22 | 500500 | 500500 | 3030 |
33 | 30003000 | 30003000 | 5050 |
本题采用捆绑测试,您只有通过了一个 Subtask 中的所有测试点才能得到这个 Subtask 的分数。
对于 100% 的数据:0≤∣∣,∣∣,∣∣,A,B,C,D≤1000, 1≤n,m≤3000。
解析:
由于吸收的能量与休息时间成一次函数关系,时间一维其实可以薅掉。
设 表示小A 用了i 把武器,小B 用了 j 把武器。后面两维分别表示当前时刻小 A 是 / 否使用了武器,当前时刻小 B 是 / 否使用了武器。
其他的贡献的计算都很简单,主要是能量吸收量的计算。以小 A 为例。
先考虑 B=0 的情况。
若小 A 当前时刻没有使用武器。小 A 的休息时间相当于多了 11 个单位时间,那么他就会再吸收 A 的能量。
直接在转移的时候减去 A 就好。
但是 怎么办?
发现加吸收B 的能量的次数与休息的次数是一致的,我们在转移的时候可以钦定一个规则:当上一时刻使用了武器,但是当前时刻没有使用武器,那么小A 的休息次数就会加 11,此时就减去 B。
剩下的就是代码了!
不准直接抄!!!
#include<bits/stdc++.h>
#define MAXN 3001
#define INF 0x3f3f3f3f
using namespace std;
int n, m, A, B, C, D;
int a[MAXN], b[MAXN], d[MAXN][MAXN];
int dp[MAXN][MAXN][2][2];
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int main(){
n = read(); m = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= m; i++) b[i] = read();
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
d[i][j] = read();
}
}
scanf("%d%d%d%d",&A,&B,&C,&D);
memset(dp, -0x3f, sizeof(dp));
dp[1][0][1][0] = a[1] - C - D;
dp[0][1][0][1] = b[1] - A - B;
dp[1][1][1][1] = a[1] + b[1] + d[1][1];
for(int i = 0; i <= n; i++){
for(int j = 0; j <= m; j++){
if(i != 0){
// dp[i][j][1][0];
dp[i + 1][j][1][0] = max(dp[i + 1][j][1][0], dp[i][j][1][0] + a[i + 1] - C);
dp[i][j + 1][0][1] = max(dp[i][j + 1][0][1], dp[i][j][1][0] + b[j + 1] - A - B);
dp[i + 1][j + 1][1][1] = max(dp[i + 1][j + 1][1][1], dp[i][j][1][0] + a[i + 1] + b[j + 1] + d[i + 1][j + 1]);
}
if(j != 0){
// dp[i][j][0][1];
dp[i + 1][j][1][0] = max(dp[i + 1][j][1][0], dp[i][j][0][1] + a[i + 1] - C - D);
dp[i][j + 1][0][1] = max(dp[i][j + 1][0][1], dp[i][j][0][1] + b[j + 1] - A);
dp[i + 1][j + 1][1][1] = max(dp[i + 1][j + 1][1][1], dp[i][j][0][1] + a[i + 1] + b[j + 1] + d[i + 1][j + 1]);
}
if(i != 0 && j != 0){
// dp[i][j][1][1];
dp[i + 1][j][1][0] = max(dp[i + 1][j][1][0], dp[i][j][1][1] + a[i + 1] - C - D);
dp[i][j + 1][0][1] = max(dp[i][j + 1][0][1], dp[i][j][1][1] + b[j + 1] - A - B);
dp[i + 1][j + 1][1][1] = max(dp[i + 1][j + 1][1][1], dp[i][j][1][1] + a[i + 1] + b[j + 1] + d[i + 1][j + 1]);
}
}
}
int ans = -INF;
for(int i = 0; i <= n; i++){
for(int j = 0; j <= m; j++){
ans = max(ans, dp[i][j][1][0]);
ans = max(ans, dp[i][j][0][1]);
ans = max(ans, dp[i][j][1][1]);
}
}
printf("%d\n",ans);
return 0;
}
Ladies and gentlemen,赶紧用你发财的小手点个赞吧!