钓鱼
枚举终点湖,剩余时间用堆贪心分配
正文
// 原题:https://oj.yecheng.tv/p/T1431
// 题意:n 个湖从左到右排列,有 H 小时,在第 i 个湖每 5 分钟钓到的鱼递减 D_i,走路耗时按 5 分钟为单位给出,求最多能钓多少鱼。
// 思路:枚举最远走到第 k 个湖,剩下的时间用优先队列在 1..k 号湖之间贪心分配。
// 1. 总时间按 5 分钟折算成 H * 12 个单位,走路只花在 1..k 之间的路程上。
// 2. 每个单位时间取当前产量最高的湖钓一次,产量下降后重新入堆。
// 3. 对所有 k 取最大值。
// 复杂度:O(n^2 log n) 时间 / O(n) 空间
// 易错点:时间是 5 分钟一个单位,H 小时要先乘 12,路程 T_i 本身就是单位数,不用再乘 5。
// 易错点:产量减到 0 之后继续钓也只得 0,但为了统一处理仍要把 0 入堆(或剩余时间直接跳过)。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, H;
if(!(cin >> n)) return 0;
if(!(cin >> H)) return 0;
vector<int> f(n), d(n), t(n);
for(int i = 0; i < n; i++) cin >> f[i];
for(int i = 0; i < n; i++) cin >> d[i];
for(int i = 0; i + 1 < n; i++) cin >> t[i];
int total = H * 12;
int best = 0;
for(int k = 1; k <= n; k++){
int time = total;
for(int i = 0; i + 1 < k; i++) time -= t[i];
if(time < 0) break;
priority_queue<pair<int, int>> pq;
for(int i = 0; i < k; i++) pq.push({f[i], i});
int sum = 0;
for(int s = 0; s < time; s++){
auto cur = pq.top();
pq.pop();
if(cur.first <= 0) break;
sum += cur.first;
pq.push({cur.first - d[cur.second], cur.second});
}
best = max(best, sum);
}
cout << best << "\n";
return 0;
}
一本通·提高篇的其它内容
- 活动安排
- 种树
- 喷水装置
- 加工生产调度
- 智力大冲浪
- 数列极差
- 数列分段
- 线段
- 家庭作业
- 糖果传递
- 愤怒的牛
- Best Cow Fences
- 曲线
- 数列分段 II
- 扩散
- 灯泡
- 传送带
- 数的划分
- 生日蛋糕
- 小木棍
- Addition Chains
- 埃及分数
- 平板涂色
- 质数方阵
- 靶形数独
- 电路维修
- 魔板
- Knight Moves
- 棋盘游戏
- Keyboarding
- 移动玩具
- 山峰和山谷
- Oulipo
- 图书管理
- Power Strings
- Seekthe Name, Seek the Fame
- Friends
- A Horrible Poem
- Beads
- Antisymmetry
- 门票
- 收集雪花
- 剪花布条
- Power Strings
- Radio Transmission
- OKR-Periods of Words
- 似乎在梦中见过的样子
- Censoring
- Phone List
- The XOR Largest Pair
- Nikitosh 和异或
- Immediate Decodability
- L 语言
- Secret Message 秘密信息
- 背单词
- The Xor-longest Path
- Keywords Search
- 玄武密码
- Censoring
- 单词