洛谷P4377 [USACO18OPEN]Talent Show G 题解 01分数规划

题目链接:https://www.luogu.com.cn/problem/P4377

解题思路:

映射关系:

  • \(w_i \rightarrow b_i\)
  • \(t_i \rightarrow a_i\)

问题转变成了01分数规划问题。但是有一个限制,就是 \(\sum w_i \times b_i \ge W\)

可以考虑01揹包。把 \(b_i\) 作为第 \(i\) 个物品的重量,\(a_i - mid \times b_i\) 作为第 \(i\) 个物品的价值,然后问题就转化为揹包了。

那么 \(dp[n][W]\) 就是最大值。

一个要注意的地方: \(\sum w_i \times b_i\) 可能超过 \(W\) ,此时直接视为 \(W\) 即可。

示例代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 255, maxw = 1010;
int n, W, a[maxn], b[maxn];
double f[maxw];
bool check(double mid) {
    f[0] = 0;
    for (int i = 1; i <= W; i ++) f[i] = -1e9;
    for (int i = 1; i <= n; i ++) {
        for (int j = W; j >= 0; j --) {
            int k = min(j+b[i], W);
            f[k] = max(f[k], f[j] + a[i] - mid * b[i]);
        }
    }
    return f[W] >= 0;
}
int main() {
    cin >> n >> W;
    for (int i = 1; i <= n; i ++) cin >> b[i] >> a[i];
    double L = 0, R = 1000;
    while (R - L > 1e-5) {
        double mid = (L + R) / 2;
        if (check(mid)) L = mid;
        else R = mid;
    }
    cout << (int) (1000 * L) << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章