洛谷p2678:经典二分答案
思路:明确答案在固定区间内,二分最短距离,对一个最短距离来说,该值最大所要移走的石头则越多,从而知道,对于区间内来说,最短距离最大值左边合法右边非法,只需要check一下判断当前最短距离是否合法。
如何判断?关键在于check函数:对每个最短距离来说,当他是最短距离时所需要移走石头数量判断当前最短距离是否合法,数量超过限制就非法,对相邻两块石头来说,如果距离小于当前最短距离,则移走右边这块,因为移走右边这块可以使得下一个石头与上一块未移走的石头间距更大,相当于减少了石头的移走数量。
代码:
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l,m,n,d[50005];
bool check(ll ans)
{
int total=0,now=0;//now标记下一次i位置要减的now位置,total表示移走石头数
for(int i=1;i<=n+1;i++)
{
if(d[i]-d[now]<ans)
{
total++;//如果对当前ans,两块石头距离小于ans,则移走当前所处第i块石头,即now位置不变,i++;
}else now=i;//如果合法,则不移走石头,即now=i,使得下一次位置与相邻位置石头距离做差
}
if(total<=m)return 1;
else return 0;
}
int main ()
{
cin>>l>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>d[i];
}
d[n+1]=l;//答案在区间[1,l]
ll left=1,right=l+1;
while(right-left>1)//二分答案
{
ll mid=(left+(right-left)/2);
if(check(mid))left=mid;
else right=mid;
}
printf("%lld",left);
return 0;
}
洛谷p3473:二分答案
思路:二分时间,模拟该时间情况下,充能多少,所有设备额外消耗能源多少,若充能大于额外耗能,则合法,小于则非法,注意边界最大时间=最大数量*最大储存能/最小耗能速率=1e5*1e5/1=1e10;精度eps=0.000001;
代码:
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
double n ,p,a[100005],b[100005];
bool check(double ans)
{
double sum=p*ans;//最大充能
double Max=0;//最大额外耗能
for(ll i=1;i<=n;i++)
{
if(ans*a[i]>b[i])
Max+=(ans*a[i]-b[i]);//额外耗能
else continue;
}
if(sum>=Max)return 1;
else return 0;
}
int main ()
{
cin>>n>>p;
for(ll i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
}
double l=0,r=1e10;
while(r-l>=0.000001)
{
double mid=(l+(r-l)/2);
if(check(mid))l=mid;
else r=mid;
}
if(l>=1e10)
cout<<"-1";
else
printf("%.10f",l);
return 0;
}