原题传送门:切绳子 - 洛谷
一道简单的二分答案,但是却让我错了将近一页。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e4+1;
int n,k;
double L[MAXN],r,ans,l,mid;
char s[100];
bool canGetKCount(){
int cnt=0;
for(int i=1;i<=n;i++){
cnt+=L[i]/mid;
}
return cnt>=k;
}
int main(){
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lf",&L[i]);
r+=L[i];
}
while(r-l>0.0001){
mid=(l+r)/2;
if(!canGetKCount()){//切不到k条,少切一点,切的更多
r=mid;
}else{
l=mid;
}
}
sprintf(s+1,"%.3f",l);
s[strlen(s+1)]='\0';
printf("%s",s+1);
/*93分代码
l=(floor(l*100.0)/100.0);
cout<<fixed<<setprecision(2)<<l<<endl;
*/
return 0;
}
二分答案的重点是要明白,l,r,mid,都是什么含义,比如这道题输出的是l,其他题目可能就是r或者mid了。这里用while(r-l>0.0001)实际上是在刷精度,类似三分法。
同时上面是cnt>=k,而不是cnt==k,因为cnt>=k都是合理的解。
93分错的那一个点下载下来输出是对的,提交就是错的..
r只要取最大的那一条乘以2就可以保证mid从最大的情况开始割,但是多了这么多步骤实际上没必要,不如直接r=INT_MAX,反正二分的效率这么高。
同时这道题是要求舍弃小数点后两位,所以可以考虑运算的时候把所有数都乘100变成整数来用,输出的时候再除以100,0即可。