类似最大(小)值最大(小)化的问题都可以用二分来解决。
可以定义一个条件 C(x) 那么就是求满足某个条件 C(X)的最小的x
如果所有的x'>=x都满足C(x'),那么就可以用二分搜索来求最小的x
左端点初始化为不满足条件的值,右端点初始化为满足条件的值,每次取中点mid,判断C(mid)是否满足并且缩小范围,直到足够小了为止。
另外,STL里的lower_bound upper_bound是求二分的函数
#include <algorithm>//必须包含的头文件 #include <stdio.h> using namespace std; int main() { int n,a[100],m; int left,right,i; scanf("%d",&n);//设初始数组内元素有n个 for(i=0;i<n;i++) scanf("%d",&a[i]); scanf("%d",&m);//插入的数为m left = upper_bound(a,a+n,m)-a;//按从小到大,m最多能插入数组a的哪个位置 right = lower_bound(a,a+n,m)-a;//按从小到大,m最少能插入数组a的哪个位置 printf("m最多能插入数组a的%d\n",left); for(i=0;i<left;i++) printf("%d ",a[i]); printf("%d ",m); for(i=left;i<n;i++) printf("%d ",a[i]); printf("\n"); printf("m最少能插入数组a的%d\n",right); for(i=0;i<right;i++) printf("%d ",a[i]); printf("%d ",m); for(i=right;i<n;i++) printf("%d ",a[i]); return 0; }
上例题!!
POJ 2456疯牛 这个是最大化最小值
【POJ】1064Cable master 这个是假定一个解并判断是否可行
最大化平均值问题:
有n个物品的重量个价值分别是wi和vi,从中选出k个物品是的单位重量的价值最大。
分析:
∑vi / ∑wi 这个式子是我们需要求的单位重量的价值。
∑vi / ∑wi >= x
∑(vi - x*wi) >= 0
判断这个式子是否成立即可。这下就可以用一个数组来保存vi - x * wi 的值,并进行排序,从大到小贪心地进行选择求和,如果求和的值大于0,那么此时 的x就是成立的。
const maxn = 2000; const int inf = 0x3f3f3f3f; int n, k; int w[maxn], v[maxn]; double y[maxn]; bool C(double x){//计算是否满足条件 for(int i=0;i<n;i++){ y[i]=v[i]-x*w[i]; } sort(y,y+n); double sum=0; for(int i=0;i<k;i++){ sum+=y[n-i-1]; } return sum>=0; } void solve(){ double lb=0,ub=inf; for(itn i=0;i<100;io++){ double min=(lb+ub)/2; if(C(mid)) lb=mid; else ub=mid; } printf("%.2f\n",ub); }