二分的用處太大了,不管是求簡單的方程,還是求最優解方面都是不錯的解題思想。
不過就像《程式設計珠璣》中說的一樣,雖然二分思路及其做法很爽,但是編寫二分的程式總是錯漏百出的。二分的第乙個程式出現在2023年,但是直到2023年出出現了第乙個沒有bug的二分程式,其編寫正確難度可想而知。
解題技巧:
(1)整形資料題目:l 為下界,r 為上界
一般的整形資料的題其迴圈都是 :
while ( l < r ) 然後l=mid+1,high=mid 這各形式的;
或者有的題目邊界要求比較強就得是
while ( l <= r) 然後 l=mid+1,r=mid-1 這各形式;
還有道題就是cf 371c那道中的邊界處理要求比較高就是:
while( l+1 < r ) 然後 l=mid,r=mid
(2)浮點型題目: #define eps 1e-5
大神說的話:「一般浮點型題目都會與精度打交道,所以勢必與eps有關,因為如果如果精度要求0.01,那麼如果你在 l=mid+eps這樣做的話,這裡我設eps為0.00001,那麼時間複雜度就會乘以10^3了,那麼既然二分是減少時間的,這樣又會增加時間複雜 度,那該怎麼避免這個problem呢。
所以在hdu 1551這題上我就掉進了這個坑了,我把精度寫在 l=mid+eps裡了,然後直接tle。 我把精度寫在while裡面的時候時間直接下降很多。因為每次都是平分,這就與eps沒多大關係了,只要能接近最優答案就行。所以技巧如下:
while( r - l >eps) 然後 l=mid , r=mid;即可。」。
解題的基本思路就是:
while( l < r )下面是這些題的**及分析:
hdu1551 cable master
算是我的二分第一題吧,題意是給你n根繩子,讓你分成長度相等m段,求繩子的最長長度。以前根本不知道這種題可以用二分來做,感覺很神奇。
**如下:
#include #includehdu4109: distributing ballot boxes#include
#include
#include
#define eps 1e-8
using
namespace
std;
intn,m;
double
sum;
double a[10001
];bool judge(double
s)
if(cnt>=m) return
true
;
else
return
false;}
intmain()
sum/=m;//繩子可以分的最大長度
double l=0,r=sum;
while(fabs(r-l)>eps)
printf(
"%.2lf\n
",l);
}return0;
}
這題就是上面那題的變形。
有n個城市,m個投票箱。
然後是n行,表示每個城市的人口數。
現在每個城市所有的人要投票,投票箱的大小可以無限大(投票箱全部相同,大小相等),我們現在要求的是最小的投票箱容納量。
解題思路:
如果n == m,則容量肯定為城市人口數最多的那個。
如果n < m,我們當然要把m全部用光,因為用的箱子越多,平均值越小。這樣,我們就可以二分列舉人口數作為投票箱的容量,如果對於當前容量,我們列舉所有城市需要 的箱子數目,小於需要的箱子就說明還可以再小,如果需要的箱子數大於給出的箱子數,說明結果不符。
ps:
函式名: ceil
用 法: double ceil(double x);
功 能: 返回大於或者等於指定表示式的最小整數
標頭檔案:
math.h
說明:float ceil ( float value )
返回不小於 value 的下乙個整數,value 如果有小數部分則進一位。ceil() 返回的型別仍然是 float,因為 float 值的範圍通常比 integer 要大。
#include #include大神的**,寫的比我的好#include
#include
#include
#define eps 1e-9//
1e-5就wa了
using
namespace
std;
intn,m;
double
maxx,mid,sum;
double a[500001
];int judge(int
r) }
if(cnt>m)
return1;
}int
main()
if(n==m)
sum/=m;
double l=sum,r=maxx;
while(fabs(r-l)>eps)
else
}printf(
"%.0lf\n
",l);
}return0;
}
#include#includeview code#include
#include
#include
#include
using
namespace
std;
int a[500010
];int
main()
if(city ==box)
l = 1, r =res;
while(l
if(flag) r = mid; //
中間值可以就減半
else l = mid + 1; //
不可以則mid+1
} printf(
"%d\n
", r);
}return0;
}
poj3273: monthly expense
題意:就是給出n個數,然後分成m組,要求分得各組的花費之和應該盡可能地小,最後輸出各組花費之和中的最大值。
感覺:二分可以求方程的解,這個我承認。不過這題確實有點神哦……這樣也能二分,太神了.
題意:二分列舉最佳的最大值,然後用最大值去列舉這n個數能分成的組數,逐漸逼近最優答案即可。
#include #includesdut2862:勾股定理(二分基礎題)#include
#include
#define inf 0x3f3f3f3f
using
namespace
std;
int n,m,maxx,a[100005
];int
sum;
bool judge(int
r) }
if(cnt<=m)
return
true
;
return
false;}
intmain()
int l=maxx,r=sum;
while(l
else l=mid+1
; }
cout
}return0;
}
校賽的題目,當時沒做出來,以後只要遇到查詢的題目首先就要考慮二分查詢,因為普通查詢時間複雜度o(n),而二分查詢是o(lgn)。
#include #include#include
#include
#include
using
namespace
std;
intn;
long
long a[1001
];bool er(long
long a,int lf,int rf,long
long
key)
else
}return
false;}
intmain()
sort(a,a+n);
for(int i=0; i<=n-3; i++)}}
cout
}return0;
}
設計模式總結(未完待續)
一 策略模式 可參看 應用場景 多種策略 演算法應用於同一用途 比如都是排序演算法 不同的情況需要用不同的策略 比如內部排序用快排,外部排序用歸併 由客戶端去決定具體呼叫哪乙個策略或演算法。一般的實現形式 每種策略類實現同乙個介面,實現演算法。由乙個context類通過構造方法引入具體的策略物件,封...
Linux學習總結 未完待續
linux學習總結 1.使用者管理部分 a,使用者與組配置檔案 a1.與使用者和組相關的配置檔案 passwd,shadow group,gshadow a2.超級許可權控制sudo的配置檔案 etc sudoers a3.新增使用者規則檔案 etc skel 預設啟動檔案 etc login.de...
未完待續 設計模式學習總結
一 設計模式的分類 1.1 根據目的分類 1 建立型 關注物件的建立過程,描述如何將物件的建立和使用分離,讓呼叫者無需關心物件的建立細節,降低耦合的同時也更易於修改和擴充套件 2 結構型 用於處理類或物件的組合,將現有類或物件組織在一起形成更加強大的結構,3 行為型 用於描述類或物件怎樣互動和怎樣分...