n (≤ 10000) 個物品,重量 W[i]、價值 V[i]。選**恰好 k** 個物品,使**單位重量價值** (ΣV / ΣW) 最大。輸出最大值(保留兩位小數)。多測試案例。
設最大值為 ans。對任意候選值 x,判斷是否存在 k 個物品使 ΣV / ΣW ≥ x。
等價變形:Σ(V[i] - x·W[i]) ≥ 0。
定義 a[i] = V[i] - x·W[i]。選最大的 k 個 a[i] 求和,若和 ≥ 0 則 x 可行。
單調性:x 越大,可行性越難。故可二分 x。
#include
#include
#include
using namespace std;
const double EPS = 1e-3;
const int MAXN = 10005;
double V[MAXN], W[MAXN];
int n, k;
bool check(double x) {
static double a[MAXN];
for (int i = 0; i < n; ++i) a[i] = V[i] - x * W[i];
sort(a, a+n, greater());
double sum = 0;
for (int i = 0; i < k; ++i) sum += a[i];
return sum >= 0;
}
int main() {
while (cin >> n >> k) {
double right = 0;
for (int i = 0; i < n; ++i) {
cin >> W[i] >> V[i];
right = max(right, V[i] / W[i]);
}
double l = 0, r = right;
while (r - l > EPS) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%.2lf\n", l);
}
return 0;
}
NYOJ「Yougth的最大化」是分數規劃(0-1 分數背包固定選 k 項)的教科書級例題。**二分答案 + 貪心檢查** 是解決此類「最大化比值」問題的通用模板,代碼簡潔、通用性強。