要求 max{F/P},先枚举下界 lowf,再贪心求符合约束条件的 n 个最小价值和 记录 F 的离散值和去重可以大幅度常数优化

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<iterator>
using namespace std;
const int maxn = 1e5+11;
typedef pair<int,int> P;
vector<P> vec[maxn];
vector<int> F;
int n,m,x,y;
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(vec,0,sizeof vec); F.clear();
        for(int i = 1; i <= n; i++){
            scanf("%d",&m);
            for(int j = 1; j <= m; j++){
                scanf("%d%d",&x,&y);
                vec[i].push_back(P(x,y));
                F.push_back(x);
            }
        }
        sort(F.begin(),F.end());
        vector<int>::iterator it = unique(F.begin(),F.end());
        F.erase(it,F.end());
        double ans=-1;
        long long tmp=0;
        for(int k = 0; k < F.size(); k++){//enum the lb of F
            int lowf=F[k];
            tmp=0;
            bool flag=0;
            for(int i = 1; i <= n; i++){
                int mn=0x7fffffff;
                for(int tt = 0; tt < vec[i].size(); tt++){
                    P t=vec[i][tt];
                    if(t.first>=lowf){
                        mn=min(mn,t.second);
                    }
                }
                if(mn==0x7fffffff)flag=1;
                tmp+=mn;
            }
            if(flag==1) continue;
            ans=max(ans,(double)lowf/tmp);
        }
        printf("%.3lf\n",ans);
    }
    return 0;
}

DP 写法

因为二维的 dp[][k] 是滚动更新的,所以每次更新当前最小值是 dp[i-1][k] 必然存在最优解

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<iterator>
using namespace std;
const int maxn = 1211;
const int oo = 0x3f3f3f3f;
typedef pair<int,int> P;
vector<P> vec[maxn];
vector<int> F;
int dp[123][maxn];//mincost when  lowf of [1..i] = j 
int n,m,x,y;
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(vec,0,sizeof vec);
        for(int i = 1; i <= n; i++){
            scanf("%d",&m);
            for(int j = 1; j <= m; j++){
                scanf("%d%d",&x,&y);
                vec[i].push_back(P(x,y));
            }
        }
        memset(dp,oo,sizeof dp);
        for(int i = 0; i < vec[1].size(); i++){
            P t = vec[1][i];
            dp[1][t.first]=min(dp[1][t.first],t.second);
        }
        for(int i = 2; i <= n; i++){
            for(int j = 0; j < vec[i].size(); j++){
                P t=vec[i][j];
                for(int k = 0; k < maxn; k++){
                    if(dp[i-1][k]!=oo){
                        if(k<=t.first)
                            dp[i][k]=min(dp[i][k],dp[i-1][k]+t.second);
                        else
                            dp[i][t.first]=min(dp[i][t.first],dp[i-1][k]+t.second);
                    }   
                }
            }
        }
        double ans=-1;
        for(int i = 0; i < maxn; i++) if(dp[n][i]!=oo) ans=max(ans,(double)i/dp[n][i]);
        printf("%.3lf\n",ans);
    }
    return 0;
}