二分法求最小值的最大值,最大值的最小值的问题
最近刚遇上了这类问题,起初苦想没有思路,在网上学习了别人的解法之后感觉到精妙异常,虽然事后知道只是一个模板题,但还是想要总结一下。
先举个例子是POJ的3273题 http://poj.org/problem?id=327
Description
Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤moneyi ≤ 10,000) that he will need to spend each day over the nextN (1 ≤ N ≤ 100,000) days.
FJ wants to create a budget for a sequential set of exactly M (1 ≤M ≤N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.
FJ's goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.
Input
Lines 2..N+1: Line i+1 contains the number of dollars Farmer John spends on theith day
Output
Sample Input
7 5 100 400 300 100 500 101 400
Sample Output
500
Hint
#include<stdio.h>
int money[100005];
int main()
{
int n,m,i,small=-1,big=0,u,sum=0,mid;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&money[i]);
if(small<money[i]) small=money[i];
big+=money[i];
}
while(small<big)
{
mid=(big+small)/2;u=1;sum=0;
for(i=0;i<n;i++)
{
if(sum+money[i]>mid)
{
u++;
sum=money[i];
}
else sum+=money[i];
}
if(u<=m)//这个小于等于的小于部分用于都一阶段也就是求出最大值区间,等于号来求这个区间的左边界
big=mid;
else
small=mid+1;
}
printf("%d\n",big);
}
Aggressive cows
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 17346 | Accepted: 8256 |
Description
His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
Input
* Lines 2..N+1: Line i+1 contains an integer stall location, xi
Output
Sample Input
5 3 1 2 8 4 9
Sample Output
3
Hint
FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.
Huge input data,scanf is recommended.
Source
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int x[100005];
int main()
{
int n,m,i,small=-1,big=0,right,left,mid,cnt,sum,num,l,r,p,u;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&x[i]);
small=min(small,x[i]);
}
sort(x,x+n);
big=x[n-1]-x[0];
num=x[n-1]/(m-1);
left=0;right=num;
while(right-left>1)
{
mid=(left+right)/2;
l=1;r=1;p=1;
while(r<n){
while(r<=n&&x[l-1]+mid>x[r-1]) r++;
if(r>n) break;
p++;l=r;if(p==m)break;
}
if(p==m) left=mid;
else right=mid;
}
printf("%d\n",left);
}
Pie
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 19777 | Accepted: 6420 | Special Judge |
Description
My friends are very annoying and if one of them gets a bigger piece than the others, they start complaining. Therefore all of them should get equally sized (but not necessarily equally shaped) pieces, even if this leads to some pie getting spoiled (which is better than spoiling the party). Of course, I want a piece of pie for myself too, and that piece should also be of the same size.
What is the largest possible piece size all of us can get? All the pies are cylindrical in shape and they all have the same height 1, but the radii of the pies can be different.
Input
- One line with two integers N and F with 1 ≤ N, F ≤ 10 000: the number of pies and the number of friends.
- One line with N integers ri with 1 ≤ ri ≤ 10 000: the radii of the pies.
Output
Sample Input
3 3 3 4 3 3 1 24 5 10 5 1 4 2 3 4 5 6 5 4 2
Sample Output
25.1327 3.1416 50.2655
Source
#include<stdio.h>
#include<math.h>
double pi[10005];
double lostpi[10005];
double area(double r)
{
return acos(-1.0)*r*r;
}
int main()
{
int n,f,much,i,sum;
double mid,big,small;
int t;
scanf("%d",&t);
while(t--)
{
small=0;big=0;
scanf("%d%d",&n,&f);
for(i=0;i<n;i++)
{
scanf("%lf",&pi[i]);
//pi[i]=area(pi[i]);
pi[i]=pi[i]*pi[i];
lostpi[i]=pi[i];
if(pi[i]>big)big=pi[i];
//printf("%lf\n",lostpi[i]);
}
while(0.000001<=big-small)
{
much=0;mid=(big+small)/2;
//printf("%lf\n",big);
for(i=0;i<n;i++)
{
lostpi[i]=pi[i];
while(lostpi[i]>=mid)
{
much++;
lostpi[i]-=mid;
//printf("PI%lf\n",lostpi[i]);printf("%d\n",much);
}
}
if(much>=f+1) small=mid;
else big=mid;
//printf("small%lfbig%lf\n",small,big);
//if(--u) continue;
//else break;
}
printf("%.4lf\n",big*acos(-1.0));
}
}