Algorithm6.1 贪心 VS 其他算法

[TOC]

二分

一些第一眼看上去是用贪心解决,但实际上是需要用其他算法解决的问题

https://www.luogu.com.cn/problem/P1570【看起来是贪心,实际上是找出答案的范围然后二分出结果】

题目大意:选取m个,然后问怎么选,才能保证属性a求和比上属性b求和的值最大

思路一:【贪心】按照属性a和属性b的比值进行排序,然后贪心的选取前m个。单个的VS求和的,有冲突

(反例:400 1和200 100 1 1)在选取了400 1之后,如果根据比例会优先选200 100,但是实际上在求和中要选1 1,

思路二:【二分】进行算式推导,推导成关于要求解的数的一个方程式,然后进行二分,来调整解,逼近解

#include <iostream>
using namespace std;
const int maxn = 205;
int n, m, a[maxn], b[maxn];
double l, mid, r;
#include <algorithm>

double check(double x) {
    double w[maxn];
    for (int i = 1; i <= n; ++i) w[i] = b[i]*x-a[i];
    sort(w+1, w+1+n);
    double tmp = 0;
    for (int i = 1; i <= m; ++i) tmp += w[i];
    return tmp;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) scanf("%d", a+i);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", b+i);
        r = max(r, a[i]*1.0/b[i]);
    }
    while (l < r && abs(r-l) > 1e-5) {
        mid = (l+r)/2;
        if (check(mid) == 0) break;
        else if (check(mid) < 0) l = mid;
        else r = mid;
    }
    printf("%.3lf\n", mid);
    return 0;
}

https://www.luogu.com.cn/problem/P1661

题目大意:n个点,问最少需要多少时间才能彼此覆盖。

思路一:贪心,直接找最长的两个点,测之间的距离,存在a到c的距离大于a到b+b到c的距离,这样几句不能绝对的

思路二:二分+并查集

思路三:最小生成树,然后看最后的边

Posted on Feb 1, 2021