二分推進演算法

2022-05-16 21:15:36 字數 2116 閱讀 3587

序:

二分搜尋是很常見的一種演算法,用來在有序序列中尋找某數(或者小於大於它的最*值的某數)。

二分答案也比較常見,估算出答案範圍後二分縮小範圍逼近答案

二分推進與二分答案很像,不同之處是二分推進並非得到答案的範圍,而是通過縮小答案對應的資料的範圍,逼近答案對應的資料(通常求最值)…

舉個例子:

平面上有n個點,已知每個點的座標。求乙個點m(x,y),使得m與其他所有點的距離和最短。(x,y的精度為0.1,最終的距離和 < 最小值+0.01即可)

思路一:暴力列舉。

由於精度是0.1,所以我們可以從minx -> maxx, miny -> maxy列舉與所有點的距離,取最小。複雜度o(100n^2),n大一點即使忽略常數100(1/0.1*1/0.1)也得tle。

思路二:二分推進。

盡然我們想到了列舉,而且我們知道最小值的座標是唯一的。(不知道怎麼證,憑直覺這應該是顯然的…)

既然如此,假設這個點是m(x,y),對於m周邊的所有點一定距離和都要大於它的距離和(否則就不是最小了)。

還有乙個隱含條件:minx<=x<=maxx; miny<=y<=maxy;

最重要的一點,越接近m的點的距離和應該越接近最小值(答案)。

知道範圍,又知道答案的特殊性與資料範圍的單調性,那麼就可以使用二分推進演算法逼近了

思路是這樣的:

1.選取範圍內的任意乙個點。

2.計算它的距離和以及它上下左右±r,也就是(x+r,y),(x,y+r)…四個座標的距離和,如果出現ans < minn,則相當於出現更優解,意味著答案應該更靠近那個點,所以我們將當前點更新為那個點繼續操作。

3.可能會出現上下左右4個點都比現在座標大,那看來是幅度太大了,r = r/2重複上一步操作。

偽**是這樣的:

while(步長大於誤差)}}

縮小步長

}

最終的座標就是答案。

**實現:

/*

about: t1 二分推進

auther: kongse_qi

date:2017/04/29

*/#include

#include

#include

#define maxn 10005

#define inf 0x7fffff

#define eps 0.01

using

namespace

std;

int n, a[maxn][2];

double maxx, maxy, minx, miny;

double ans[2], cur_ans = inf;

void read()

return ;

}double cal(double x, double y)

return ans;

}void solve()

, dicy = ;

double ne_ans;

cur_ans = cal(curx, cury);

while(r >= eps)}}

r *= 0.5;

}ans[0] = curx;

ans[1] = cury;

return ;

}int main()

這與啟發式搜尋很像,但是還沒有搞懂怎個啟發式。作為與二分答案法的姊妹演算法,暴力**後也可以看看能否通過二分優化。

至此結束。

箜瑟_qi 2017.04.29 23:49

二分推進演算法

序 二分搜尋是很常見的一種演算法,用來在有序序列中尋找某數 或者小於大於它的最 值的某數 二分答案也比較常見,估算出答案範圍後二分縮小範圍逼近答案。二分推進與二分答案很像,不同之處是二分推進並非得到答案的範圍,而是通過縮小答案對應的資料的範圍,逼近答案對應的資料 通常求最值 舉個例子 平面上有n個點...

演算法基礎 二分查詢函式 二分演算法

一 寫乙個函式binaryseach,在包含size個元素的 從小到大排序的int數a裡查詢元素p,如果找到,則返回元素下標,如果找不到,則返回 1。要求複雜度o log n int binarysearch int a,int size,int p return 1 複雜度o log n 二 寫乙...

演算法 二分查詢演算法

思想 二分搜尋主要解決的問題是確定排序後的陣列x 0,n 1 中是否包含目標元素target。二分搜尋通過持續跟蹤陣列中包含元素target的範圍 如果target存在陣列中的話 來解決問題。一開始,這個範圍是整個陣列,然後通過將target與陣列中的中間項進行比較並拋棄一半的範圍來縮小範圍。該過程...