题解 P1717 【钓鱼】
这道题数据范围比较小,所以我们可以先不考虑时间复杂度(貌似关于
以下字母
引理 约翰不会掉头
证明:由于每个鱼塘能钓到的鱼与当前时间戳无关,掉头只会白白浪费时间,所以约翰不会掉头
Q.E.D.
思路 DP
考虑设计状态 dp[i][j] 表示处于第 i 个鱼塘,花费了 j 单位时间,钓到了 dp[i][j] 条鱼。
考虑转移。从 dp[i][j] 转移到 dp[k][p] ,当且仅当:
转移方程式为
其中
初始化 f[0][0] 为 0 ,其余均为 -inf (注:转移时
注意代码中的
时间复杂度
代码
已略去头文件 & I/O优化
// 自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只
// 要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也
// 能够保持自己的本色走下去。 ——陈立杰
/*************************************
* @problem: P1717 钓鱼.
* @user_id: 63720.
* @user_name: brealid.
* @time: 2020-06-01.
* @language: C++.
* @upload_place: luogu.
*************************************/
const int N = 25 + 4, HT = 16 * 60 + 7;
int H, n;
int f[N], d[N], t[N];
int fish[N][HT];
int dp[N][HT];
#define dist(l, r) (t[r] - t[l])
signed main() {
n = read<int>();
H = read<int>() * 12;
for (int i = 1; i <= n; i++) f[i] = read<int>();
for (int i = 1; i <= n; i++) d[i] = read<int>();
for (int i = 2; i <= n; i++) t[i] = t[i - 1] + read<int>();
for (int i = 1; i <= n; i++) {
int now = f[i];
for (int j = 1; j <= H; j++) {
fish[i][j] = fish[i][j - 1] + now;
now = max(now - d[i], 0);
}
}
memset(dp, 0xcf, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
for (int k = dist(j, i); k <= H; k++) {
for (int p = k; p <= H; p++) {
dp[i][p] = max(dp[i][p], dp[j][k - dist(j, i)] + fish[i][p - k]);
}
}
}
}
// for (int i = 1; i <= n; i++)
// for (int j = 0; j <= H; j++)
// printf("%-3d%c", dp[i][j], " \n"[j == H]);
int ans = 0;
for (int i = 1; i <= n; i++) ans = max(ans, dp[i][H]);
write(ans, 10);
return 0;
}
// Create File Date : 2020-06-01
/*
Input
2 1
10 1
2 5
2
*/