最近又碰到了二分法的题目,可惜题都没读懂(好像后来读懂了也没啥用),于是决定做几道二分的巩固一下。
一:
题目链接: HDU 1969 Pie
思路分析
利用二分法找能平均分到的最大体积,如果要按这个体积数分,而分得的人数少于总人数,说明这个体积数大了,就向小的体积数继续查找。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-6;
const double pi=acos(-1.0);
int main()
{
int T,N,F,i,a[10001],temp;
double sum,l,r,mid;
cin>>T;
while(T--)
{
sum=0;
cin>>N>>F;
for(i=1;i<=N;i++)
{
cin>>a[i];
sum+=a[i]*a[i]*pi;
}
l=0,r=sum/(F+1);
while(r-l>eps) //注意double类型的比较
{
temp=0;
mid=(l+r)/2.0;
for(i=1;i<=N;i++)
temp+=(int)((a[i]*a[i]*pi)/mid); //此体积数下,能够分给多少人,注意取整。
if(temp<F+1)
r=mid;
else
l=mid;
}
printf("%.4f\n",mid);
}
}
二:
题目链接: Hdu 1551 Cable master
思路分析
和上面的题几乎相同,依旧是注意精度问题。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-10;
int main()
{
int N,K,i,time;
double l,r,sum,a[10001],mid;
while(cin>>N>>K && N)
{
for(i=1;i<=N;i++)
{
cin>>a[i];
sum+=a[i];
}
l=0,r=sum/K;
while(r-l>eps)
{
time=0;
mid=(l+r)/2;
for(i=1;i<=N;i++)
time+=(int)(a[i]/mid);
if(time<K)
r=mid;
else
l=mid;
}
printf("%.2lf\n",mid);
}
}
三
题目链接: HDU 2199 Can you solve this equation?
思路分析
这个也没什么分析的了,就是套二分的模板了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-10;
int main()
{
int T,n;
double l,r,mid;
cin>>T;
while(T--)
{
cin>>n;
l=0,r=100;
if(n<6 || 8*pow(100,4) + 7*pow(100,3) + 2*pow(100,2) + 3*100 + 6 <n)
printf("No solution!\n");
else
{
while(r-l>eps)
{
mid=(l+r)/2;
if(8*pow(mid,4) + 7*pow(mid,3) + 2*pow(mid,2) + 3*mid + 6 >n)
r=mid;
else if(8*pow(mid,4) + 7*pow(mid,3) + 2*pow(mid,2) + 3*mid + 6 <=n)
l=mid;
}
printf("%.4f\n",mid);
}
}
}
四:
题目链接: HDU 3258 River Hopscotch
思路分析
最小值最大化,就用二分了,只不过判断的过程需要想一想,N-M+1代表删掉M个数之后剩余的区间数目,如果counter大于这个数目,说明此时正在判断的数字过小,否则则过大。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
int L,N,M,a[50005];
const int inf=0x3f3f3f3f;
int elect(int x)
{
int p=0,i,counter=0;
for(i=1;i<=N+1;i++)
{
if(a[i]-p>=x)
{
counter++;
p=a[i];
}
}
return counter<N-M+1;
}
int main()
{
int l,r,i,mid;
cin>>L>>N>>M;
for(i=1;i<=N;i++)
cin>>a[i];
a[0]=0;
a[N+1]=L;
sort(a,a+N+2);
l=1,r=L;
while(l<=r)
{
mid=(l+r)/2;
if(elect(mid))
r=mid-1;
else
l=mid+1;
}
cout<<l-1<<endl;
}
以后继续补充,感觉二分有些细节又清楚了许多。