luoguP4377 01分数规划 背包dp

简介: luoguP4377 01分数规划 背包dp
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;
}
相关文章
|
7月前
|
存储
LeetCode热题 首题 两数之和
LeetCode热题 首题 两数之和
44 1
|
7月前
|
算法 JavaScript
class074 背包dp-分组背包、完全背包【算法】
class074 背包dp-分组背包、完全背包【算法】
53 0
|
7月前
|
算法
class075 背包dp-多重背包、混合背包【算法】
class075 背包dp-多重背包、混合背包【算法】
73 0
|
2月前
lanqiao OJ 3513 岛屿个数(2023省赛)
lanqiao OJ 3513 岛屿个数(2023省赛)
16 2
|
2月前
|
算法
lanqiao OJ 1366 spfa最短路
lanqiao OJ 1366 spfa最短路
26 0
|
2月前
lanqiao OJ 207 大臣的旅费(两次dfs)
lanqiao OJ 207 大臣的旅费(两次dfs)
14 0
华为机试HJ44:Sudoku(数独问题,深度优先遍历DFS解法)
华为机试HJ44:Sudoku(数独问题,深度优先遍历DFS解法)
146 0
|
7月前
|
算法 测试技术
每日一题:LeetCode-LCR 007. 三数之和
每日一题:LeetCode-LCR 007. 三数之和
|
7月前
|
机器学习/深度学习 算法 索引
leetcode热题100.两数之和
leetcode热题100.两数之和
37 1
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(3)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(3)
113 0