emmm……看到题面“总才艺值与总体重的比值最大”,那么这个就是01分数规划问题了。 现在详细讲一讲如何解决这类问题。 先看简单一点的题: 有 n 个物品,有属性值 ai,bi要求选出至多 k 个物品,使得sum(ai) / sum(bi)尽可能大。 我们要首先二分答案 x,若 sum(ai) / sum(bi) ≥x 则说明答案可以更大。 稍微变形一下:sum(a[i]) >= sum(b[i]) * x; 继续:sum(a[i] - b[i] * x) >= x 我们发现 i 对答案的贡献是个常数 ai-bi了! 由于至多选 k 个物品,我们可以贪心,将 ai-bix从大到小排序,然后选出前 kk 个前缀和的最大值。如果是非负数那么答案就可以变得更大。 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e4 + 5; const ll inf = 1e18; ll w[maxn], t[maxn]; ll dp[maxn]; int N, W; ll check(ll mid) { for (int i = 0; i < maxn; i++) { dp[i] = -inf; } dp[0] = 0; for (int i = 1; i <= N; i++) { for (int j = W; j >= 0; j--) { if (dp[j] != -inf) { int jj = j + w[i]; jj = min(jj, W); dp[jj] = max(dp[jj], dp[j] + t[i] - (ll) w[i] * mid); } } } return dp[W] >= 0; } ll solve() { ll l = 0, r = 1e7; while (l <= r) { ll mid = (l + r) / 2; if (check(mid)) { l = mid + 1; } else { r = mid - 1; } } return l - 1; } int main() { cin >> N >> W; for (int i = 1; i <= N; i++) { cin >> w[i] >> t[i]; t[i] *= 1000; } cout << solve() << endl; return 0; }