NC14662 小咪买东西

题目

  • 原题地址:小咪买东西
  • 题目编号:NC14662
  • 题目类型:01分数规划
  • 时间限制:C/C++ 1秒,其他语言2秒
  • 空间限制:C/C++ 131072K,其他语言262144K

1.题目大意

  • n个物品,有价值v和价格c,选出k个物品,求max(总价值/总价格)

2.题目分析

  • 感觉不是很懂为啥用二分。。。按照原来思路做WA了(直接按照v/c比排序,再加和相除)
  • 想明白了:
  • 原来的思路:直接按照v/c比排序,再选出前k个加和,总的v和总的c相除
  • 正确的思路:二分单位价值x,check函数里按照v-c*x来排序,如果前k个的v-c*x之和>0,就返回true
  • 为什么原来的思路不对:就是因为靠后的物品如果vc都大,会把最终结果向它靠近,不如选择v/c小的,让其影响不了大v/c的物品占比多少
  • eg:8,2;9,3;40,20;1,1
  • (8+9+40)/(2+3+20)=57/25<3
  • (8+9+1)/(2+3+1)=3

3.题目代码

#include <bits/stdc++.h>

using namespace std;

const int INF = 0x3f3f3f3f;
const int MAX = 1e4 + 7;
int n, k;
int c[MAX], v[MAX];
double w[MAX];

bool judge(double x) {
    for (int i = 1; i <= n; i++)
        w[i] = v[i] - x * c[i];
    sort(w + 1, w + 1 + n, greater<double>());
    double sm = 0;
    for (int i = 1; i <= k; i++)
        sm += w[i];
    return sm > 0;
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> k;
        for (int i = 1; i <= n; i++)
            cin >> c[i] >> v[i];
        double l = 0, r = INF;
        for (int i = 1; i <= 100; i++) {
            double mid = (l + r) / 2;
            if (judge(mid)) l = mid;
            else r = mid;
        }
        cout << (int)r << endl;
    }
    return 0;
}
posted @ 2022-08-23 14:56  仪战群儒  阅读(61)  评论(0)    收藏  举报