有 $N$ 个鱼塘排成一排,每个鱼塘中有一定数量的鱼,例如:$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 分钟内可钓到 10 条鱼,第 2 分钟内只能钓到 8 条鱼,……,第 5 分钟以后再也钓不到鱼了。
从第 1 个鱼塘到第 2 个鱼塘需要 3 分钟,从第 2 个鱼塘到第 3 个鱼塘需要 5 分钟,……
给出一个截止时间 T,设计一个钓鱼方案,从第 1 个鱼塘出发,希望能钓到最多的鱼。
假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。
数据范围
$1≤N≤100$ ,
$1≤T≤1000$
思路:
首先明确一点,从某一鱼塘中每分钟能钓上的鱼数只有在到达该鱼塘后才会开始减少。
对样例进行分析可以发现,每个鱼塘每分钟能钓上鱼的数量是等差数列。
能用于钓鱼的总时间:
其中:全部时间 ,走到鱼塘 $i$ 花费的总时间。
由于每次都是从$1$号鱼塘出发,因此可以枚举每次最终到达的鱼塘编号$i$, 并求此时的最大钓鱼数。
由于时间间隔都是$1$分钟,接下来的工作就是在等差数列$1$到等差数列$i$的所有数值中,选取前$T_{钓鱼}$个值。这显然是一个多路归并问题。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <iostream> #include <cstring> using namespace std;
const int N = 110; int f[N], d[N], t[N], spend[N];
int get(int i) { return max(0, f[i] - d[i] * spend[i]); }
int check(int n, int T) { int res = 0; memset(spend, 0, sizeof(spend)); while(T--) { int j = -1; for(int i = 1; i <= n; ++i) if(j == -1 || get(i) > get(j)) j = i; res += get(j), ++spend[j]; } return res; }
int main() { int n, T, res = 0; cin >> n; for(int i = 1; i <= n; ++i) cin >> f[i]; for(int i = 1; i <= n; ++i) cin >> d[i]; for(int i = 1; i < n; ++i) cin >> t[i], t[i] += t[i - 1]; cin >> T; for(int i = 1; i <= n; ++i) res = max(res, check(i, max(0, T - t[i - 1]))); cout << res << endl; return 0; }
|