在算法竞赛题目中,有两种题型:整数二分、 实数二分。
- 整数域上的二分, 注意终止边界、左右区间的开闭情况, 避免漏掉答案或者死循环。
- 实数域上的二分, 需要注意精度问题。
之前迷惑了好久的边界问题,在这里总结一下:
整数二分:
- :分割 、、,循环条件
- :分割 、、,循环条件
实数二分:
- :分割、
【整数二分】
模板:
bool check(int mid)
{
if(根据题意判断) return true;
else return false;
}
int left, right, ans;
while(left <= right)
{
int mid = left+(right-left)/2; //二分
if(check(mid)) //根据题意检查条件,如果成立
{
ans = mid; //记录答案
left = mid + 1; //移动left(或right)
}
else
{
right = mid - 1; //移动right(或left)
}
}
模板:
bool check(int mid)
{
if(根据题意判断) return true;
else return false;
}
int left, right, ans;
while(left < right)
{
int mid = left+(right-left)/2; //二分
if(check(mid)) //根据题意检查条件,如果成立
{
ans = mid; //记录答案
left = mid + 1; //移动left(或right)
}
else
{
right = mid; //移动right(或left)
}
}
所以, 二分法的难点在于如何建模和check()条件,其中可能会套用其他算法或者数据结
构。
【实数二分】
实数域上的二分比整数二分简单。
模板:
//精度。若保留k位小数,eps一般取10^-(k+2)
const double eps = 1e-7; //如果下面用for,可以不要eps
bool check(double mid)
{
if(根据题意判断) return true;
else return false;
}
double BinSearch(double left, double right)
{
//for(int i = 0; i < 100; i++)
while(right - left > eps)
{
double mid = left+(right-left)/2;
if(check(mid)) left = mid; //根据题意判定,然后继续二分
else right = mid;
}
return left; //right也对
}
其中, 循环用 种方法都可以:
如果用 循环, 由于循环内用了二分, 执行 次, 相当于实现了 的精度, 一般比 更精确。
循环的 次, 比 的循环次数要多。 如果时间要求不是太苛刻, 用 循环更
简便。
来源:CSDN
作者:菜是原罪QAQ
链接:https://blog.csdn.net/qq_42815188/article/details/104069861