思路
因為此題撒網的時間和位置都是未知的,所以必須列舉出一個。
又因為時間有可能是一個小數,不好列舉,因此考慮列舉位置。
首先,有一個顯然的貪心策略,每一次撒網的位置的左端點一定是一條魚。
那麼,我們不妨列舉撒網位置的左端點為第 \(i\) 條魚。
然後可以算出其餘的魚能被一起捕到的時間段。
那麼,問題就轉變為了,在一堆時間段中,取一個點,使得這個點所在的時間段的權值之和最大。
直接用差分維護一個即可。
Code
#include <bits/stdc++.h>
#define re register
using namespace std;
const int N = 2010;
const double eps = 1e-9;
int n,len,ans;
int w[N],x[N],v[N];
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
int main(){
n = read();
len = read();
for (re int i = 1;i <= n;i++){
w[i] = read();
x[i] = read();
v[i] = read();
}
for (re int i = 1;i <= n;i++){
map<double,int> mp;
int res = w[i];
for (re int j = 1;j <= n;j++){
if (i == j) continue;
if (v[i] == v[j]){//當 v[i] = v[j] 時,i 和 j 的相對位置不變,判斷 0 時刻能否被捕到即可
if (x[j] >= x[i] && x[j] - x[i] <= len) res += w[j];
}
else{
double l = 1.0 * (x[i] - x[j]) / (v[j] - v[i]);//算出左右端點
double r = 1.0 * (x[i] - x[j] + len) / (v[j] - v[i]);
if (r - l < eps) swap(l,r);
if (r >= 0){
l = max(l,0.0);
mp[l] += w[j];
mp[r + eps] -= w[j];
}
}
}
ans = max(ans,res);
for (auto it = mp.begin();it != mp.end();it++){
res += it -> second;
ans = max(ans,res);
}
}
printf("%d",ans);
return 0;
}