最大化最小值(二分值最小越小越容易满足条件,求最大值)
区间长度为1时的写法:
解的范围为 [lb,rb][lb,rb]
// 计算区间为[lb, rb]
while( rb > lb ) // 区间长度为1时终止循环
{
// 防止溢出
int m = lb + (rb - lb + 1) / 2; // 由于是区间长度为1时终止循环,所以要加1
if( ok(m) ) lb = m;
else rb = m - 1;
}
// 跳出循环时 lb == rb
区间长度为2时的写法:
解的范围为 [lb,rb)[lb,rb)
while( rb - lb > 1 ) // 区间长度为2时终止循环
{
// 防止溢出
int m = lb + (rb - lb) / 2; // 由于是区间长度为2时终止循环,所以不用加1(不会死循环)
if( ok(m) ) lb = m;
else rb = m;
}
// 跳出循环时 lb + 1 == rb
// 答案为 lb
最小化最大值(二分值越大越容易满足条件,求最小值)
区间长度为1时的写法:
解的范围为 [lb,rb][lb,rb]
while( rb > lb )
{
// 防止溢出
int m = lb + (rb - lb) / 2; // 这里虽然区间长度为1,但不需要加1(不会死循环)
if( ok(m) ) rb = m;
else lb = m + 1;
}
// 跳出循环时 lb == rb
区间长度为2时的写法:
解的范围为 (lb,rb](lb,rb]
while( rb - lb > 1 )
{
// 防止溢出
int m = lb + (rb - lb) / 2;
if( ok(m) ) rb = m;
else lb = m;
}
// 跳出循环时 lb + 1 == rb
// 答案为 rb
浮点数的二分,100次循环可以达到2^-100(约为10^-30)的精度范围
以最大化最小值为例(即小于该数的解均满足条件)
for( int i = 0; i < 100; ++ i )
{
double m = (lb + rb) / 2;
if(check(m)) lb=m;
else rb=m;
}
// 跳出循环时 lb 与 rb 近似相等,所以都可作为答案
三分搜索:https://blog.csdn.net/u011787119/article/details/44598871
double solve(double parameter)
{
// 计算函数值,即f(x)
}
double trisection_search(double left, double right)
{
// 三分搜索,找到最优解(求函数最大值下的自变量值)
double midl, midr;
while (right-left > 1e-7)
{
midl = (left + right) / 2;
midr = (midl + right) / 2;
// 如果是求最小值的话这里判<=即可
if(solve(midl) >= solve(midr)) right = midr;
else left = midl;
}
return left;
}