牛客-wyh的物品——通过验证得出二分的搜索区间
这篇题解展示了一个“答案二分 + 可行性验证”的经典分数优化模型。建模思路目标值是“最大单位价值”,属于连续实数区间搜索。通过设定候选值 mid 把原问题转化为验证问题。验证成立与否用于指导二分收缩方向。验证函数核心对每个物品计算变换值 s[i] = v[i] - w[i] * mid。排序后取前 k 个最大值求和。和…
题目 题目链接 题目详解 以下为手写详解 下面总结这个做题步骤:二分搜索可能的最大单位价值。根据这个值得到每个数的单位价值情况s,根据s的值排序,得到前k大的s,相加得出我们枚举的这个最大单位价值是大了还是小了,方便后续二分! 最后按保留两位小数,输出即可。解题代码#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; int w[maxn],v[maxn]; double s[maxn]; //TODO 存下用于比对实际单位价值的信息 int n,k; using namespace std; int solve(double mid) { double ss = 0; for(int i = 0;i<n;i++) { s[i] = 1.0*v[i] - w[i]*mid; } sort(s,s+n,greater<double>());//TODO 从大到小排序,因为要取前k个最大值 for(int i = 0;i<k;i++) ss += s[i]; //TODO 得到前k个最大的s信息的和, // 如果大于0,则说明取小了,小于0则取大了,等于0则正好满足! if(ss>0) return 1; else if(ss==0)return -1; else return 0; } int main() { int t; cin>>t; while(t--) { scanf("%d %d",&n,&k); double low = 0,high = 100000,mid; for(int i = 0;i<n;i++) { scanf("%d %d",&w[i],&v[i]); } //TODO 二分搜索,由于double类型的二分,故取一个小数形式进行比对 // 注意double类型的二分,千万别+1或者-1!这个跨度太大了,因为我们搜的是个分数! while(high - low >0.00001) { mid = (low + high)/2.0; int flag = solve(mid); if(flag==1) low = mid;//TODO 收缩左边界 else if(flag == -1)break;//TODO 枚举得到答案 else high = mid;//TODO 收缩右边界 } printf("%.2lf\n",mid); } return 0; }
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行