1. 程式人生 > >淺談二分答案

淺談二分答案

二分答案,就是二分列舉答案,由於進行二分,所以複雜度log(n),比直接
for的時間更短。

【問題描述】

記得上學那會, Fbs同學經常會欺負蘿蔔同學。有一次,他出了這麼一道題目,想為難一下蘿蔔同學。題目是這樣的: 有N個整數X_i, X_i值的範圍從0到1000000000。要從中選出C個數( 2<=C<=N),使得任意兩個數差的絕對值的最小值儘可能大,求這個最大值。 由於資料太大, 這次蘿蔔同學的確被難住了,怎麼辦呢,請你來幫幫蘿蔔同學吧!
【輸入格式】
第一行是N和C。
接下來的N行,每行一個整數。
【輸入格式】
一個整數,表示兩兩最小差距的最大值。
【輸入輸出樣例】
aggr.in aggr.out
5 3
1
2
8
4
9
3
【樣例解釋】
選擇1、 4和8或者選擇1、 4和9。
【資料說明】
對於 30%的資料: 2<=N<=100;
對於 60%的資料: 2<=N<=1000;
對於 100%的資料: 2<=N<=100000, 2<=C<=N, 0<=X_i<=1000000000。

這題只要二分列舉絕對值差的最大值,直接暴力列舉這個值,即可求出

#include<bits/stdc++.h>
using namespace std;
int i,j,k,n,m,tot,ans,l,r,mid,f[100005],use,c,s1;
int read(){
    char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
    int x=0,y=1;if(c=='-') y=-1;else x=c-'0';
    while(c=getchar(),c>='0'&&c<='9'
) x=x*10+c-'0'; return x*y; } int main() { n=read();c=read(); for(int i=1;i<=n;i++) f[i]=read(); sort(f+1,f+1+n); l=1,r=1000000000; while(l<r-1){ mid=(l+r)>>1;s1=1;use=1; for(int i=2;i<=n;i++){ if(f[i]-f[s1]>=mid){ use++; s1=i; } } if
(use>=c) l=mid; else r=mid; } printf("%d",l); return 0; }

題目描述

有N條繩子,它們的長度分別為Li。如果從它們中切割出K條長度相同的

繩子,這K條繩子每條最長能有多長?答案保留到小數點後2位。

輸入輸出格式

輸入格式:
第一行兩個整數N和K,接下來N行,描述了每條繩子的長度Li。

輸出格式:
切割後每條繩子的最大長度。

輸入輸出樣例

輸入樣例#1:
4 11
8.02
7.43
4.57
5.39
輸出樣例#1:
2.00

這題是二分答案,只不過答案是小數,所以二分的時候要注意精度,注意浮點數誤差。
只要列舉小數,算出ans,就可以完成答案。

#include<bits/stdc++.h>
using namespace std;
int i,j,k,ans,use,n;
double f[100006],l,r,mid;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>f[i];
    }
    l=(double)1.00,r=(double)100000.00;
    while(l<r-0.0000001){
        mid=(l+r)/2;ans=0;
        for(int i=1;i<=n;i++) 
           ans+=f[i]/mid;
        if(ans>=k) l=(double)mid;
        else r=(double)mid;
    }
    printf("%.2f",l);
    return 0;
}