二分、三分總結

簡單描述

在決策過程中,使得達到平衡度高。常常因爲我們的算法是要解決一類問題,一個好的算法往往要考慮的卻是最壞的情況。對於二分,我們要做的是選擇出期望值,其實可以想想每次最多能排除多少可以可能值。


應用

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;
}


三分

應用

查找可以被分割成小於或等於兩個單調性區間的拋物線的臨界值


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章