poj 几道简单的二分题
poj 3273 Monthly Expense
题意:
有n个数,划分成m块,和最大的一块最小是多少?
分析:
最大值最小问题,二分答案。
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N],n,m;
bool ok(int x)
{
int k=m,t=0; //k是块数,t是某一块的和
for(int i=0;i<n;i++){
if(t+a[i]<=x){
t+=a[i];
}
else{
t=0;
k--;
i--;
}
if(k<0)return false;
}
return k>0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
int l=0,r=1e9;
while(l<r){
int m=l+(r-l)/2;
if(ok(m))r=m;
else l=m+1;
}
printf("%d\n",l);
return 0;
}
poj 3258 River Hopscotch
题意:
一条河L宽,河中间有n个落脚点,问移走m个落脚点后,过河时,跨越的最短距离最大是多少?
分析:
读完这题,最小值最大问题,先想到二分答案,但是仔细想了想之后觉得不行,因为这是确定的移走m块石头,就拿样例来讲,如果二分答案是3,那么只能移走一块石头(2),不行,如果二分答案是5,那么要移走三块石头,也不行。左右都不行还怎么二分啊?于是写了个贪心,WA了。后来又仔细想了想,其实对于答案是3这种情况,我们可以认为这是可行的(虽然没移够m块,但是继续二分可以得到最优解)。所以这题二分就可以了。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N],n,m,L;
bool ok(int x)
{
int pre=0;
for(int i=1;i<=n-m;i++){
int cur=pre+1;
while(cur<=n&&a[cur]-a[pre]<x)cur++;
if(cur==n+1)return false; //移走的数量超过了m块
pre=cur;
}
return true;
}
int main()
{
//freopen("f.txt","r",stdin);
scanf("%d%d%d",&L,&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+1+n);
a[0]=0;
a[++n]=L;
int l=0,r=L;
while(l<r){
int m=l+(r-l+1)/2;
if(ok(m))l=m;
else r=m-1;
}
printf("%d\n",l);
return 0;
poj 1905 Expanding Rods
题意:
固定的钢管热膨胀,会向上弯曲,求上升的高度?
分析:
求一下边角关系,然后二分答案即可。
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int main()
{
double L,n,c;
while(~scanf("%lf%lf%lf",&L,&n,&c)){
if(L<0&&n<0&&c<0)break;
double s=(1+n*c)*L;
double l=0,r=0.5*L;
while(r-l>1e-6){
double m=(l+r)/2;
r=(4*m*m+L*L)/8/m;
if(2*r*asin(L/2/r)<s)l=m;
else r=m;
}
printf("%.3f\n",l);
}
return 0;
}
poj 3122 Pie
题意:
有n个圆Pie,每个半径ri,有m+1个人,问每个人分相同面积的一片Pie,最大的面积可能是多少?
分析:
二分答案,然后判断即可。
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const double PI=acos(-1.0);
const int N=1e4+9;
double s[N];
int n,m,r;
bool ok(double x)
{
int cnt=0;
for(int i=0;i<n;i++){
double t=s[i];
while(t>x)t-=x,cnt++;
}
return cnt>=m+1;
}
int main()
{
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&r);
s[i]=PI*r*r;
}
double l=0,r=PI*10000*10000;
while(r-l>1e-6){
double m=(l+r)/2;
if(ok(m))l=m;
else r=m;
}
printf("%.4f\n",l);
}
return 0;
}