首先我们可以枚举要走过湖泊数X,然后算出从1到X的时间。那么在这个前提下,我们可以认为fisher可以从一个湖泊“瞬间转移”到另一个湖泊,即在任意一个时刻可以从1到X中任选一个钓鱼。
此时,走路的时间确定了,钓鱼的次数就确定了(每次5分钟),然后每次都选取f[i]最大的钓,这种贪心的思想最终能够得到一个钓鱼序列。
你可能会跟我一样有一个疑问:因为就算是在这种情况下求出的钓鱼序列 为 1 ,5,6, 2, 3, 2,7 ,你可能会认为到了湖泊6之后再回到湖泊2可能要再花时间而且题目也不允许,但是这只是钓鱼序列,我们可以用 1 2 2 3 5 6 7 来实现这种钓鱼序列。但是总的来说求这种钓鱼序列比求实现更加容易,我用的是 o(n^2)的枚举,如果用堆的话可以进一步优化。
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int main(){
int N, H;
int f[30], d[30], t[30];
int T, Case = 1;
cin >> T;
while( T-- ){
cin >> N >> H;
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];
}
int fishtimes, ans_times[30], max_ans = 0;
memset( ans_times, 0, sizeof( ans_times ) );
for( int i = 1; i <= N; i++ ){
int temp = 0;
for( int j = 1; j < i; j++ ){
temp += t[j] * 5;
}
fishtimes = ( H * 60 - temp ) / 5;
int temp_f[30], temp_ans_times[30], temp_max_ans = 0;
memset( temp_ans_times, 0, sizeof( temp_ans_times ) );
for( int j = 1; j <= i; j++ ) temp_f[j] = f[j];
for( int j = 1; j <= fishtimes; j++ ){
int tp = 1;
for( int k = 1; k <= i; k++ ){
if( temp_f[k] > temp_f[tp] ){
tp = k;
}
}
temp_max_ans += temp_f[tp];
temp_f[tp] -= d[tp];
if( temp_f[tp] < 0 ){
temp_f[tp] = 0;
}
temp_ans_times[tp] += 5;
}
if( temp_max_ans > max_ans ){
for( int i = 1; i <= N; i++ ){
ans_times[i] = temp_ans_times[i];
}
max_ans = temp_max_ans;
}
}
cout << "Case " << Case++ << ":" << endl;
cout << ans_times[1];
for( int i = 2; i <= N; i++ ){
cout << ", " << ans_times[i];
}
cout << endl;
cout << "Number of fish expected: " << max_ans << endl;
}
return 0;
}