[题解]AT_abc274_f [ABC274F] Fishing

思路

因为此题撒网的时间和位置都是未知的,所以必须枚举出一个。

又因为时间有可能是一个小数,不好枚举,因此考虑枚举位置。

首先,有一个显然的贪心策略,每一次撒网的位置的左端点一定是一条鱼。

那么,我们不妨枚举撒网位置的左端点为第 \(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;  
}  
posted @ 2024-06-23 00:26  WBIKPS  阅读(22)  评论(0)    收藏  举报