#隔离
【题目描述】
鸡尾酒要从 𝐴 地去 𝐵 地办 𝑛 件事,其中第 𝑖 件事耗时 𝑎[𝑖] 分钟,办完之后回到 𝐴 地。但是如果他在 𝐵 地连续待的时间大于等于 240 分钟,那么行程卡中就会显示他去过 𝐵 地。根据 𝐴 地的防控政策,如果去过 𝐵 地,那么就会被隔离 7 天(10080 分钟),隔离之后才能继续正常行动(例如再启程去𝐵 地,或者在 𝐴 地开始正常生活)。于是他有一个对策,即在 240 分钟快到的时候就从 𝐵地回到 𝐴 地,然后再去 𝐵 地,这样 240 分钟就会重新计时,从 𝐴 地往返一趟 𝐵 地耗时 400 分钟。现在他在 𝐴 地准备出发,想要在 𝐵 地办完所有事, 回 𝐴 地开始正常生活,办 𝑛 件事的顺序无法打乱,且办每一件事的过程中无法 打断。请问他至少需要多少分钟?
【输入格式】 第一行包含一个正整数 𝑛,表示事情的个数。
接下来包含 𝑛 个正整数,表示办每一件事所需要消耗的时间 𝑎[𝑖]。
【输出格式】
输出一行一个数字表示答案。
【样例 1 输入】
1
240
【样例 1 输出】
10720
【样例 1 说明】
去过 𝐵 地的时间大于等于 240 分钟就会被隔离,所以鸡尾酒会被隔离 7 天,隔离后才能进行正常生活。所以总耗时为 400 + 240 + 10080(其中 400 是来回 𝐵 地的时间)。注意不能将 240 分钟的事情拆解成两次来办,因为办一件事的过程不能被打断。
【样例 2 输入】
2
120 121
【样例 2 输出】
1041
【样例 2 说明】
往返一次办第一件事,再往返一次办第二件事。共耗时 400 + 120 + 400 + 121 = 1041
【数据范围】
对于 20% 的数据,有 𝑛 = 1 对于 40% 的数据,有 1 ≤ 𝑛 ≤ 2 对于另外 10% 的数据,有 240 ≤ 𝑎[𝑖] 对于 100% 的数据,有 1 ≤ 𝑛, 𝑎[𝑖] ≤ 1000
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int calculateTime(int n, vector<int> &a) {
const int trip = 400; // A地到B地往返一次所需时间
vector<int> dp(n, 0);
// 初始化第一件事的情况
dp[0] = a[0] + trip; // 完成第一件事并返回A地所需时间
for (int i = 1; i < n; ++i) {
dp[i] = dp[i-1] + a[i] + trip; // 默认情况下,完成当前任务并返回A地
// 检查是否需要返回A地再次出发
for (int j = i-1; j >= 0; --j) {
if (dp[j] + a[i] <= 240) {
// 如果加上下一件事的时间不超过240分钟,则可以在B地完成
dp[i] = min(dp[i], dp[j] + a[i]);
break; // 由于顺序不能打乱,一旦找到一个符合条件的j,就可以跳出循环
} else {
// 如果超过240分钟,则需要返回A地,重新开始计时
dp[i] = min(dp[i], dp[j] + trip + a[i]);
}
}
}
// 如果最后dp[n-1]的值小于等于240,则不需要加上隔离时间
return dp[n-1] <= 240 ? dp[n-1] : dp[n-1] + 10080;
}
int main() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
cout << calculateTime(n, a) << endl;
return 0;
}