簡單描述
在決策過程中,使得達到平衡度高。常常因爲我們的算法是要解決一類問題,一個好的算法往往要考慮的卻是最壞的情況。對於二分,我們要做的是選擇出期望值,其實可以想想每次最多能排除多少可以可能值。
應用
1、必須具有單調性
2、把決策問題轉化爲判定性問題,來解決最優化問題
A:查找某個正確的結果
B:查找某個值的的區間
C:二分逼近求根號
D:對於二維有序數組,可以二分在嵌套二分
E:對於多維可以多次嵌套
F:青蛙過河問題,給定河寬L,n個石墩,最多用m步,求每一步最少跳多遠,能跳過河。點擊打開HDU題目鏈接
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500005
using namespace std;
int L,n,m,a[N],b[N];
int get_ans( int x )
{
if( x<b[0]) return -1;
int sum=0,num=0;
for( int i=0; i<=n; i++ )
{
if ( b[i] > x ) return -1;
sum+=b[i];
if( sum>x )
{
num++;
sum=b[i];
}
if( num>=m ) return -1;
}
if( sum>x )num+=2;
else if ( sum > 0 ) num++;
if( num>m ) return -1;
else return 1;
}
int main()
{
//freopen("in.txt","r",stdin);
while( cin>>L>>n>>m )
{
for( int i=0; i<n; i++ )
{
scanf("%d",&a[i]);
}
sort(a,a+n);
b[0]=a[0];
for(int i=1; i<n; i++ )
{
b[i]=a[i]-a[i-1];
}
b[n]=L-a[n-1];
int mid,l=b[0]-1,r=L+6;
while( l<=r )
{
mid = (l+r)/2;
int t = get_ans(mid);
if( t==-1 ) l=mid+1;
else r=mid-1;
}
printf("%d\n",r+1);
}
return 0;
}
G:給你n個數,讓分成m個連續的組,求在分得組中,使得組和的最大值最小。poj 題目鏈接
#include<cstdio>
#define N 100010
using namespace std;
int a[N],n,m;
int work(int left,int right)
{
int mid;
while(left<=right)
{
mid=left+(right-left)/2;
int sum=0,temp=0;
bool flag=true;
for(int i=0;i<n;i++)
{
if(mid<temp+a[i])
{
temp=a[i];
sum++;
if(sum>=m)
{
if(i+1==n&&sum==m)flag=true;
else flag=false;
break;
}
}
else temp+=a[i];
}
if(!flag)left=mid+1;
else right=mid-1;
}
return mid;
}
int main()
{
int i,j,mx=0;
int sum=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
if(a[i]>mx) mx=a[i];
}
printf("%d\n",work(mx,sum));
return 0;
}
三分
應用
查找可以被分割成小於或等於兩個單調性區間的拋物線的臨界值