一、题目
1. 描述
John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to. For each i = 1,...,n - 1, the number of 5-minute intervals it takes to travel from lake i to lake i + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 means that it takes 20 minutes to travel from lake 3 to lake 4. To help plan his fishing trip, John has gathered some information about the lakes. For each lake i, the number of fish expected to be caught in the initial 5 minutes, denoted fi( fi >= 0 ), is known. Each 5 minutes of fishing decreases the number of fish expected to be caught in the next 5-minute interval by a constant rate of di (di >= 0). If the number of fish expected to be caught in an interval is less than or equal to di , there will be no more fish left in the lake in the next interval. To simplify the planning, John assumes that no one else will be fishing at the lakes to affect the number of fish he expects to catch.
Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent at each lake must be a multiple of 5.
大意是: jhon去钓鱼,他有h(1 <= h <= 16)个小时的时间,一共有n(2 <=n <= 25)个湖, 这些湖都在一条直路上, jhon开始从第一号湖开始行进, 他可以在任意一个湖停下。他只能从第i(1 <= i <= n-1)个湖走到第i+1个湖, 这个过程花费的时间为ti(0 < ti <= 192), 注意ti的值代表有几个五分钟,例如t3=4,代表从第3号湖到第4号湖花费4*5 = 20分钟。 第i个湖第一个五分钟内有fi(fi >= 0)条鱼, 之后每过五分钟鱼的数量都会减少di(di >= 0),如果湖中鱼的数量小于等于di, 那么之后鱼的数量为0
2. 输入
You will be given a number of cases in the input. Each case starts with a line containing n. This is followed by a line containing h. Next, t> here is a line of n integers specifying fi (1 <= i <=n), then a line of n integers di (1 <=i <=n), and finally, a line of n - 1 integers ti (1 <=i <=n - 1). Input is terminated by a case in which n = 0. 第一行为n, 当n为0时程序停止 第二行为h 第三行为n个整数,为每个湖初始的鱼量 第四行为n个整数,为每个湖每五分钟鱼减少的量 第五行为n-1个整数,为ti
3. 输出
For each test case, print the number of minutes spent at each lake, separated by commas, for the plan achieving the maximum number of fish expected to be caught (you should print the entire plan on one line even if it exceeds 80 characters). This is followed by a line containing the number of fish expected.
If multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at lake 2, and so on. Insert a blank line between cases.
4. 样例
(1) 样例输入
2
1 10 1 2 5 2 4 4 10 15 20 17 0 3 4 3 1 2 3 4 4 10 15 50 30 0 3 4 3 1 2 3 0
(2) 样例输出
45, 5
Number of fish expected: 31
240, 0, 0, 0
Number of fish expected: 480
115, 10, 50, 35
Number of fish expected: 724
二、思路分析
n最大为25且jhon的起点固定,则可以枚举出jhon的终点i,也就是他在哪个湖停下来。
每一次枚举终点后,采用贪心的思想,假设他可以在湖之间瞬移,只要先把总时间h减去他在路上花费的时间,剩下的时间就都用来钓鱼。
设总时间减去路程时间为th,最终钓鱼数为ans, 暂时的钓鱼数为now,最终时间向量times[N], 暂时的时间tmp[N]。那么问题现在变为在th时间内并且终点为第i个湖的情况下,怎么钓最多的鱼。只要用贪心的思想,每次都找出鱼最多的湖j,now加上fj(钓鱼),tmp[j]加1(在第j个湖上花费的时间加1), th减1(当前可用钓鱼时间减1), fj减去dj(湖中鱼的数量减少di), 当fi<=dj时,fi更新为0。 重复上述过程,当th变为1时结束,最后将ans与now比较大小,更新times和ans
三、数据结构
int n, h, now, //暂时钓鱼数
th,//每次枚举的有效时间
ans;//最终钓鱼数量结果
int d[MAXN], // 减少的数量
t[MAXN], // 路上时间
tmp[MAXN],//每次各湖钓鱼时间
times[MAXN];//最终的钓鱼时间
struct Lake{
int fish, No;
bool operator< (const Lake& other) const{
//鱼数相同,则编号小的在前, 编号必须排序,不然a不了
return fish==other.fish ? No>other.No : fish < other.fish;
}
}lakes[MAXN];
priority_queue<Lake> q; // 大根堆,鱼量最多的湖在堆顶
四、算法
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int MAXN = 25 + 5;
int n, h, now,
th,//每次枚举的有效时间
ans;//最终钓鱼数量结果
int d[MAXN],
t[MAXN],
tmp[MAXN],//每次各湖钓鱼时间
times[MAXN];//最终的钓鱼时间
struct Lake{
int fish, No;
bool operator< (const Lake& other) const{
//鱼数相同,则编号小的在前
return fish==other.fish ? No>other.No : fish < other.fish;
}
}lakes[MAXN];
priority_queue<Lake> q;
int main(){
while(scanf("%d %d", &n, &h) != EOF && n){
for(int i=1; i<=n; i++){
scanf("%d", &lakes[i].fish);
lakes[i].No = i;
}
for(int i=1; i<=n; i++){
scanf("%d", &d[i]);
}
for(int i=1; i<n; i++){
scanf("%d", &t[i]);
}
h *= 12;//转换为时间片的数量、
ans = -1;//有可能钓不到任何鱼,但他还是要在湖待着,所以不能设置为0
for(int i=1; i<=n; i++){
h -= t[i-1];//减去步行时间
memset(tmp, 0, sizeof(tmp));
now = 0;
while(!q.empty()) q.pop();
for(int j=1; j<=i; j++) q.push(lakes[j]);
th = h;//有效钓鱼时间
while(th > 0){
Lake lake = q.top();
q.pop();
now += lake.fish;
th--;
tmp[lake.No]++;
lake.fish -= d[lake.No];
lake.fish = max(0, lake.fish);//如果鱼数为负,设为0
q.push(lake);
}
if(now > ans){//更新结果和时间、
ans = now;
for(int i=1; i<=n; i++)
times[i] = tmp[i];
}
}
printf("%d", times[1] * 5);
for(int i=2; i<=n; i++)
printf(", %d", times[i] * 5);
printf("\nNumber of fish expected: %d\n\n", ans); // 最后将时间片的数量*5, 为具体分钟数
}
return 0;
}