問題解決yzoj1663:怒りウシ(二点)yzoj1662:曲線(第3)

ポイントとオフ仕上げない話題の3分の2は、私はノートの下に整理するために、これらの2つの質問を取る必要があることを言います

私のために長い時間の特定の境界半分のための二分法についてまず話は、すべての側面をチューニングするために変更を撮影している、形而上学的な質問です。一般的なアイデアは、左境界線Lと境界R、狭い条件決意を決定することです。

おそらくコードを置きます

while(l+ep<r){
      lm=l+(r-l)/3.0;
      rm=r-(r-l)/3.0;
      if(clu(lm)>clu(rm)) l=lm;
      else r=rm;
}

半分は一般的な答えの半分だけでなく、バ​​イナリ検索で使用、非常に有用であることが証明、一般的に最大の参照または最小、最大、最小、バイナリまたはバイナリ検索回答質問です、一般的な二分法の回答ルーチンの質問が広く一致しています。

二値答え:luoguのP1182、P2678

バイナリ検索:luoguのP1496(+個別のバイナリサーチ)

おそらく他の2点を作るために左と右の範囲の半分に基づいて約3分の1、3は最も一般的に単一のピーク関数の値を決定するために使用して下さい

第1の2値の中間値と同様

mid=(l+r)>>1

右、その後、中間値半ばに取ります

rmid=(mid+r)>>1

F(RMID)のに値f(MID)の範囲を狭くします

もちろん、書くための別の方法があります

値は、左/ 3 +におけるn / 3の←N 1全体の最初のセクションをLMID。

インターセクションは三つのセルに分割されているように2右中間部側とは、値RMID←右-N / 3を取ります。

の値を絞り込むために3. F(LMID)F(RMID)の値

   double ep=1e-9;
   while(l+ep<r){//使用ep来控制精度
      lm=l+(r-l)/3.0;
      rm=r-(r-l)/3.0;
      if(clu(lm)>clu(rm)) l=lm;
      else r=rm;
   }

Oのような時間計算量(lon3n)

トピックに戻ります

1.怒っている牛

問題の意味:n個の納屋に異なる距離で離間牛Cは、任意の二つの最小要件は、最大距離牛を離隔しました

この質問のために、私たちは、細部へのこだわりを検索することができ、バイナリ形式

#include<bits/stdc++.h>
using namespace std;
int n,l,r,c,a[100010];
int main(){
    scanf("%d %d",&n,&c);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    l=0,r=a[n];
    while(l<=r){
        int mid=(l+r)>>1;
        int cnt=1;//初始值为1,把第一头牛放到一号牛舍一定最优
        int tmp=a[1];
        for(int i=1;i<=n;++i){
            if(a[i]-tmp>=mid){
                cnt++;
                tmp=a[i];
            }
        }
        if(cnt<c) r=mid-1;
        else l=mid+1;
    }
    printf("%d",r);
    return 0;
} 

2.曲線

問題の意味:N次関数、i番目のG(X)の二次関数= AI X BI ^ 2 + X + CI([1、N - ] \(iはイプシロン\ \) )(二次関数は、に分解することができます線形関数)、F(X)=最大値 (G(x))(nは最大値)の二次関数
で需要F(X)\(X \イプシロン[0、 1000] \) であり、最小値、李証明書F(x)は単峰性関数であり、次の3つのポイントを見つけることができます

#include<bits/stdc++.h>
using namespace std;
int T,n;
double ep=1e-9;//控制精度
double a[10010],b[10010],c[10010];
double clu(double x){
    double sum=0;
    for(int i=1;i<=n;++i) sum=max(sum,((a[i]*x)+b[i])*x+c[i]);//展开即为g(x)
    return sum;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%lf %lf %lf",&a[i],&b[i],&c[i]);
        }
        double l=0,r=1000,lm=0,rm=0;
        while(l+ep<r){
            lm=l+(r-l)/3.0;
            rm=r-(r-l)/3.0;
            if(clu(lm)>clu(rm)) l=lm;
            else r=rm;
        }
        printf("%.4lf\n",clu(l));
    }
    return 0;
} 

おすすめ

転載: www.cnblogs.com/donkey2603089141/p/11414852.html