淺談二分答案
二分答案,就是二分列舉答案,由於進行二分,所以複雜度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;
}