poj 1064二分+精度(重要的是细节问题!)1064

以前大体了解二分的思想,只知道大大简化时间复杂度,但没有真正手敲,于是发现很多细节问题:

①二分大体是确定要查找的对象!(一般是长度等有序数据!但在某些问题用个数,这时通常与前缀和结合)→将被查找数据写入数组(要排序!二分查找的对象核心是单调!单调!单调!或者说有序)初始化左右端点(确定上下界)→限定查找范围(while的条件)→

if-else(查找满足的条件)(一般另写一个函数)

{

端点移动(一般left=mid+1,right=mid-1)

}

→选值(二分最后取左端点,还是右端点,还是这一个区间,要看写法)

 

需要思考的:

查谁

单调(有些并不明显,比如最大化最小值问题,即搜索的距离越大,分组数越小,距离和分组存在单调关系)

上下界  poj 3273  https://blog.csdn.net/zjyang12345/article/details/80272253

判条件   poj 3104 和最大化平均值问题

①Judge函数怎么写? (难的用到贪心算法,或数学公式设变量找关系)       

②看每个小区间取不取得到端点,poj1064向下取整、2456、3258最大化最小值区间左闭右开,取不到最值;poj3273最小化最大值区间左开右闭,取得到最值。

取端点  poj2456等 最大值最小化的问题,一般我习惯取L。

附:while和left、right写法,看代码。

 

精度方面:

①精度控制大体范围eps,但有时for循环50-100次就足够了。

四舍五入保留小数之间的差异。

③强制类型转换注意加括号的范围

 

本题大佬题解

#include<iostream>

#include<iomanip>
#include<stdio.h>
#include<cmath>
using namespace std;
double L[10010];
int Judge(double mid,int N)
{
int sum=0;
for(int i=0;i<N;i++)
{
sum+=L[i]/mid;//不小心将L[i]强制转换成int,WA到死
}
//cout<<sum<<endl;
return sum;
}
int main()
{
int N,K;
scanf("%d%d", &N, &K);  
double r=1e5+1;
double l=0;
double mid;
for(int i=0;i<N;i++)
{
scanf("%lf", &L[i]);  
}
while(r-l>=1e-10)//精度必须控制得当,但1e-15的话容易陷入死循环
//for(int i=0;i<100;i++) //挑战上面的方法
{
mid=(l+r)/2;
// cout<<"mid="<<mid<<endl;
if(Judge(mid,N)>=K)
l=mid;


else 
r=mid;

}
   //mid=3.567;
   int m=(int)(r*100);
  double p=(double)m/100.0;
// cout<<fixed<<setprecision(2)<<r<<endl;//这是四舍五入操作
printf("%.2f\n", p);//题目要求的是保留小数点而不是四舍五入,而且取得是右端点(最大值)
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值