二分的幾種簡單應用——入門
---恢復內容開始---
說起二分,最基礎的二分搜索算法就不用了吧(最難的還際應用啊感覺)……實現起來很簡單,搜索區間不斷減半……唔……嘛……簡單甩個模板好了(●‘?‘●)
下面開始學習二分的幾種應用啦~~
1.假定一個解並判斷是否可行
一般用於求解判斷條件較為簡單的最大化和最小化的問題,不斷縮小答案的區間。
怎麽說呢……舉個栗子好了
Cable master POJ - 1064
Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a "star" topology - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.
To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants as far from each other as possible.
The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter,and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not known and the Cable Master is completely puzzled.
You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.Input The first line of the input file contains two integer numb ers N and K, separated by a space. N (1 = N = 10000) is the number of cables in the stock, and K (1 = K = 10000) is the number of requested pieces. The first line is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 meter and at most 100 kilometers in length. All lengths in the input file are written with a centimeter precision, with exactly two digits after a decimal point.
Output
Write to the output file the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits after a decimal point.If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output file must contain the single number "0.00" (without quotes).
Sample Input
4 11
8.02
7.43
4.57
5.39
Sample Output
2.00
題意:給出n段繩子的長度,要求割出的段數,求每段的最大長度。
設bool型函數C(x):每段繩長為x時,可以割出K段繩子
那麽題目就變成了求x的最大值,一開始將答案的區間範圍設為(0,inf)
我們所要做的就是不斷縮小答案所在的區間,直至區間的左右邊界最接近。
用二分的方法,在C(x(mid))返回true時,說明x偏小(x>=最大值),讓x變大,取原區間的左區間中點繼續判斷;
返回false時,說明x偏大,讓x變小,取原區間的左區間中點繼續判斷
直至區間縮小至最小,輸出區間上界即可
不太明白為什麽有的二分輸出的是區間上界,有的是下界,有大佬給講講麽
orz啊 ,WA了無數次……精度大坑啊……/(ㄒoㄒ)/~~記筆記記筆記
幾個關於精度的問題:
①double轉int的時候……記錄每根繩子可以分為幾段的時候crt=(int)(a[i]/x);加括號!!!不要忘了加括號!(敲黑板啊!)
②關於二分的循環次數,改用for(int i=0;i<100;i++),避免eps選取不當陷入死循環的問題,100次循環可以達到1e-30的精度範圍
③floor(<cmath>)向下取整
④double型scanf用%lf,printf用%f!!!!
#include<iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<algorithm> using namespace std; typedef long long ll; double n,a[10005],sum; int k; bool C(double x) { int crt=0; for (int i = 0; i < n; i++) crt +=(int)(a[i] / x); return crt >= k; } int main() { while (scanf("%lf%d", &n,&k)!=EOF) { sum = 0; for (int i = 0; i < n; i++) { scanf("%lf",&a[i]); } double l = 0, h = 0x3f3f3f3f; for(int i=0;i<100;i++) { double mid = (l + h) / 2; if (C(mid)) l = mid; else h = mid; } printf("%.2f\n", floor(h * 100) / 100 ); } return 0; }
2.最大化最小值
道理跟上面差不多,最大化最小值或者最小化最大值的問題,通常可以用二分+貪心判斷來解決
舉個栗子,一起看一看
Aggressive cows POJ - 2456
Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).
His C (2 <= C <= N) cows don‘t like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?Input
* Lines 2..N+1: Line i+1 contains an integer stall location, xi
Output
* Line 1: One integer: the largest minimum distanceSample Input
5 3 1 2 8 4 9
Sample Output
3
Hint
OUTPUT DETAILS:FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.
Huge input data,scanf is recommended.
題意:大概就是有n個牛舍,c頭牛,給出牛舍的位置,問牛舍的安排方案中,牛與牛之間最小值最大是多少 判斷函數:C(d):牛與牛之間的距離不小於d 貪心:①對牛舍的位置進行排序 ②第一頭放入x0 ③第i頭牛放入xj,第i+1頭放入xj+d<=xk的最小的k中 ④判斷是否能安排好c頭牛,是→增大d;否→減小d;
#include<iostream> #include<stdio.h> using namespace std; int n,c,a[100010]; bool C(int d) { int t = a[0],crt=1; for (int i = 1; i <n; i++) { if (a[i] - t >= d) { t = a[i]; crt++; if (crt >= c) return true; } } return false; } int main() { while (scanf("%d%d", &n,&c)!=EOF) { for (int i = 0; i < n; i++) scanf("%d",&a[i]); sort(a, a + n); int l = 0, h = a[n-1]-a[0]; while(l<h-1) { int mid = (l + h) / 2; if (C(mid)) l = mid; else h = mid; } printf("%d\n", l ); } return 0; }
3.最大化平均值
emmmmm……這類大部分都要先推出個式子呢……雖說是對平均值進行最大化的處理,但是卻很難直接判斷如何處理平均值……
舉個栗子,體會體會
K Best POJ - 3111
Demy has n jewels. Each of her jewels has some value vi and weight wi.
Since her husband John got broke after recent financial crises, Demy has decided to sell some jewels. She has decided that she would keep k best jewels for herself. She decided to keep such jewels that their specific value is as large as possible. That is, denote the specific value of some set of jewels S = {i1, i2, …, ik} as
.
Demy would like to select such k jewels that their specific value is maximal possible. Help her to do so.
Input
The first line of the input file contains n — the number of jewels Demy got, and k — the number of jewels she would like to keep (1 ≤ k ≤ n ≤ 100 000).
The following n lines contain two integer numbers each — vi and wi (0 ≤ vi ≤ 106, 1 ≤ wi ≤ 106, both the sum of all vi and the sum of all wi do not exceed 107).
Output
Output k numbers — the numbers of jewels Demy must keep. If there are several solutions, output any one.
Sample Input
3 2
1 1
1 2
1 3
Sample Output
1 2
題意:給出n件物品的重量和價值,問從n件物品中取k件,取那些可以使單位重量的價值最大
唔,最容易想到的方法是,根據物品的單位重量的價值大小排序以後貪心的去取,但是這種方法是不正確的。
另外一種方法就是先確定最大的單位重量的價值(後面用s表示),然後取滿足v-x*w>=0的物品。
因為最大的單位重量價值s=∑vi/∑wi(i為最優方案)>=x(其他方案的平均價值),稍作化簡可以得到
∑(vi-x*wi)>=0也就是說最優方案的k件物品滿足上述條件,我們只需要按每件物品的上式值排序,貪心的取前k件,判斷其和是否>=0
一直在TLE……改天A了再貼代碼
---恢復內容結束---
二分的幾種簡單應用——入門