有 N N N 个鱼塘排成一排,每个鱼塘中有一定数量的鱼,例如: N = 5 N=5 N=5 时,如下表:
鱼塘编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
第1分钟能钓到的鱼的数量(1…1000) | 10 | 14 | 20 | 16 | 9 |
每钓鱼1分钟钓鱼数的减少量(1…100) | 2 | 4 | 6 | 5 | 3 |
当前鱼塘到下一个相邻鱼塘需要的时间(单位:分钟) | 3 | 5 | 4 | 4 |
即:在第 1 1 1 个鱼塘中钓鱼第 1 1 1 分钟内可钓到 10 10 10 条鱼,第 2 2 2 分钟内只能钓到 8 8 8 条鱼,……,第 5 5 5 分钟以后再也钓不到鱼了。
从第 1 1 1 个鱼塘到第 2 2 2 个鱼塘需要 3 3 3 分钟,从第 2 2 2 个鱼塘到第 3 3 3 个鱼塘需要 5 分钟,……
给出一个截止时间 T T T,设计一个钓鱼方案,从第 1 1 1 个鱼塘出发,希望能钓到最多的鱼。
假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。
输入格式
共
5
5
5 行,分别表示:
第 1 1 1 行为 N;
第 2 2 2 行为第 1 1 1 分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;
第 3 3 3 行为每过 1 1 1 分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;
第 4 4 4 行为当前鱼塘到下一个相邻鱼塘需要的时间;
第 5 5 5 行为截止时间 T T T。
输出格式
一个整数(不超过
2
31
−
1
2^{31}−1
231−1),表示你的方案能钓到的最多的鱼。
数据范围
1
≤
N
≤
100
,
1
≤
T
≤
1000
1≤N≤100,\\ 1≤T≤1000
1≤N≤100,1≤T≤1000
输入样例:
5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14
输出样例:
76
- 思路
枚举
我是看了刘汝佳的书,其实我一直没想明白,为什么用贪心,如何用,心里面一直都不清楚。
仔细想了才清楚。因为每次钓鱼只能选择左半段进行活动。那么枚举左半段即可。
第一次枚举:只能在 1 , 1, 1,池塘里面钓鱼。
第二次枚举:只能在 1 , 2 1,2 1,2池塘里面钓鱼。
第三次枚举:只能在 1 , 2 , 3 1,2,3 1,2,3池塘里面钓鱼。
第i次枚举:只能在 1 , 2 , 3 , i 1,2,3,~~~i 1,2,3, i池塘里面钓鱼。
直到最后一个池塘。
贪心
对于每一次枚举用贪心算法。由于对于第 i i i次枚举,对于所有的枚举到的池塘 ( 1 (1 (1~ i ) i) i)来说,都是要路过的。并且都是从左至右的方式进行路过。
那么跑路的时间就是恒定的。余下的时间直接用来钓鱼。去掉了跑路的时间,题又简单了一半。
接下来看怎么贪心。
这里有个很大的限制是,钓鱼是必须从左边的池塘向右边的池塘一个接一个地钓鱼。
首先我们想一下如果不是一个接一个地钓鱼会是什么结果。
我们每次都是选择鱼最多的来钓。其实结果都是一样的。
比如
第一次我们选择在 1 1 1号池塘钓鱼。 t 1 t1 t1
第二次我们选择在 2 2 2号池塘钓鱼。 t 2 t2 t2
第三次我们又选择在 1 1 1号池塘钓鱼。 t 3 t3 t3
与
第一次我们在 1 1 1号池塘钓鱼用了 t 1 + t 3 t1+t3 t1+t3时间
第二次我们走到 2 2 2号池塘钓鱼用了 t 2 t2 t2时间。
效果是一样的。钓鱼的数量是一样的。
所以贪心的策略就是每次钓鱼的时候选择鱼最多的来钓鱼。(这里可以用一个最大堆来做)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int inf = 0x3f3f3f3f;
const int maxn = 110;
priority_queue<pii> q;
int f[maxn], d[maxn], t[maxn];
int n;
int T;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &f[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &d[i]);
}
for (int i = 1; i <n; i++) {
scanf("%d", &t[i]);
}
scanf("%d", &T);
int mx = -inf;
int walk_time = 0;
for (int k = 1; k <= n; k++) {
int rest_time = T - walk_time;
int ans = 0;
while (!q.empty()) q.pop();
for (int i = 1; i <= k; i++) {
q.push({f[i], i});
}
while (rest_time > 0 && q.top().first > 0) {
pii p = q.top();
q.pop();
ans += p.first;
p.first -= d[p.second];
q.push(p);
rest_time--;
}
mx = max(ans, mx);
walk_time += t[k];
}
printf("%d\n", mx);
return 0;
}