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的距离,这样几句不能绝对的
思路二:二分+并查集
思路三:最小生成树,然后看最后的边