日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蛮力法-分治法-处理最近对问题

發布時間:2023/12/8 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蛮力法-分治法-处理最近对问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

兩種方法對最近對問題的解釋

背景描述:

??終于,隔了將近一周,開始更新第二篇算法博客。今天的問題是最近對問題。問題描述如下:對于二維坐標系中的若干個點,從中判斷出相距最近的兩個點,并輸出最近的這個距離。
??我之前也翻看了很多篇博客,大家都解釋的很好,但是都只是輸出了最近的距離,而我希望這個程序不僅能輸出最近距離,同時還能鎖定是哪兩個點得到的這個最近距離。于是,經過反復試錯后,終于得到滿意的結果,馬不停蹄過來更新博客了。

蠻力法:

??首先介紹蠻力法的思路。顧名思義,就是從第一個點開始,求它和第二個點之間的距離,然后求它和第三個點之間的距離,依次往后遍歷。經過兩重循環之后就可以得出最短的距離,同時鎖定是哪兩個點產生的。
??可以設置兩個一維數組,一個存儲橫坐標,另一個存儲縱坐標,注意要兩個數組彼此之間一一對應。完整算法如下(由于蠻力法較為簡單,此處只給出算法部分,完整程序請參考下面分治法):

//返回最短長度,并得到該兩個點在數組中的下標索引index1和index2 float Getclosedpoint(int *x, int *y, int n, int &index1, int &index2) {float min = (x[0] - x[1])*(x[0] - x[1]) + (y[0] - y[1])*(y[0] - y[1]);float path;for (int i = 0; i < n - 1; i++){for (int j = i + 1; j < n; j++){path = (x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]);if (path <= min){min = path;index1 = i;index2 = j;}}}return min; }

蠻力法時間復雜度分析:

??假設有n個點,則從外層循環是從第一個數字開始,循環到第n-1個數停止,共循環n-1次。內層循環一開始從第一個數開始,遍歷求與后面所有的點之間的距離,共n-1次,最后一次循環從第n-1個數開始,求和第n個數之間的距離,執行1次。所以共執行1+2+…+(n-2)+(n-1)=n(n-1)/2;所以時間復雜度O(n2).

分治法

??分治法顧名思義是分而治之,將一個大問題分解成幾個小問題再逐個解決。對于最近對問題,分治法的思路如下:
??1.首先將這些雜亂的點按照橫坐標進行排序,然后取中間值mid將這堆點分成左右兩部分。
??2.分別對左邊和右邊的兩小堆點集再次遞歸使用分治法,進而得到對應的最短距離d1和d2。
??3.接下來處理mid中間線部分的情況。因為有一種可能就是距離最短的兩個點一個在左區域一個在右區域。因此我們要對這種情況進行解決。辦法是從剛才第二步中的兩個結果中取最小值d,然后以步驟1中的中間值mid為基準,劃分出寬度為2d的一個區域,然后將這個區域中的點進行蠻力法求得對應的最短距離d3。
??4.最后將結果進行比較。
??算法的完整程序如下:

#include<iostream> #include<math.h> #include<time.h> using namespace std;struct point {int x, y; };//對數組R[low]到R[hjgh]之間進行一次劃分,返回劃分之后中樞軸的位置 int Partition(point *R, int low, int high) {int pivotkey;R[0] = R[low];pivotkey = R[low].x;while (low < high){while (low < high&&R[high].x >= pivotkey)high--;if (low < high)R[low++] = R[high];while (low < high&&R[low].x <= pivotkey)low++;if (low < high)R[high--] = R[low];}R[low] = R[0];return low; } //對記錄序列R[s..t]進行快速排序 void Sort(point *R, int s, int t) {int pivotloc;if (s < t){pivotloc = Partition(R, s, t);Sort(R, s, pivotloc - 1);Sort(R, pivotloc + 1, t);} } //對數組R[]進行快速排序 R[0]為哨兵單元 void QuickSort(point *R, int n) {Sort(R, 1, n - 1); }double Distance(point a, point b) {return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); }int index(double x, point *S, int low, int high) {for (int i = 0; i < high - low + 1; i++){if (S[i].x <= x && S[i + 1].x > x)return i;} }//對點坐標數組S[low]和S[high]之間的元素進行遞歸查找,返回其中最近的兩個點之間的距離 //其中loc1,loc2表示這兩個點在S[]中的下標 double Closest(point S[], int low, int high,int &loc1,int &loc2) {double d1, d2, d3, d;int a1, b1, a2, b2; //用于遞歸時記錄最近對點的坐標int mid;int n1 = 0; //遞歸函數中,用來表示最近對的下標int n2 = 0;if (high - low == 1) //只有兩個點{loc1 = low;loc2 = high;return Distance(S[low], S[high]);}if (high - low == 2) //只有三個點,求最近距離{d1 = Distance(S[low], S[low + 1]);d2 = Distance(S[low + 1], S[high]);d3 = Distance(S[low], S[high]);if ((d1 < d2) && (d1 < d3)){loc1 = low;loc2 = low + 1;return d1;}else if (d2 < d3){loc1 = low + 1;loc2 = high;return d2;}else{loc1 = low;loc2 = high;return d3;}}mid = (low + high) / 2; //計算中間點d1 = Closest(S, low, mid, a1, a2); //遞歸求解子問題1d2 = Closest(S, mid + 1, high, b1, b2); //遞歸解決子問題2if (d1 < d2) //以下求解子問題3{d = d1;loc1 = a1;loc2 = a2;}else{d = d2;loc1 = b1;loc2 = b2;}//篩選范圍 S[mid].x-d, S[mid].x+dint index1 = 0;int index2 = 0;for (int i = 0; i < high - low + 1; i++){if (S[i].x <= S[mid].x - d && S[i + 1].x > S[mid].x - d){index1 = i;break;}}for (int i = 0; i < high - low + 1; i++){if (S[i].x <= S[mid].x + d && S[i + 1].x > S[mid].x + d){index2 = i;break;}}//對S[index1]和S[index2]之間進行蠻力法for (int i = index1; i < index2 - index1; i++){for (int j = i + 1; j < index2 - index1; j++){if (S[j].y - S[i].y >= 0)break;else{d3 = Distance(S[i], S[j]);if (d3 < d){d = d3;loc1 = i;loc2 = j;}}}}return d; }int main() {point *S = new point[11];int x[10] = { 12,14,4,77,89,9,99,96,77,93 };int y[10] = { 13,56,55,67,34,21,65,78,87,22 };S[0].x = 0;S[0].y = 0;for (int i = 1; i < 11; i++){S[i].x = x[i - 1];S[i].y = y[i - 1];}QuickSort(S, 11);int index1 = 0;int index2 = 0;cout << Closest(S, 1, 10, index1, index2) << endl;//cout << index1 << " " << index2 << endl;cout << "(" << S[index1].x << "," << S[index1].y << ") 和 (" << S[index2].x << "," << S[index2].y << ")" << endl;cout << "The run time is:" << (double)clock() / CLOCKS_PER_SEC << "s" << endl; }

分治法的時間復雜度分析

??對于分治法,假設有k個數,當k=2時,時間復雜度為:T(n)=1;
當k>2時,時間復雜度為T(n)=2T(n/2)+n;對這樣的遞推式最終得到T(n)=O(nlog2n )。

算法總結

??對于分治法,有三點總結:1.寫遞歸函數時,一定一定一定要考慮到遞歸跳出的情況,寫出這種情況時如何return。2.對于確定點的坐標,遞歸函數中將index作為引用參數,傳入函數體內,這種思路沒毛病,需要注意的是,在函數體內再次調用遞歸函數時,傳入的引用不能再是index,要用新的變量。否則的話index就得不到想要的值。3.對于遞歸函數,也是可以用new函數動態分配內存空間的,如果報錯,原因極可能是代碼出錯。
??最后的最后,這幾天莫名的有些焦慮。因為挑戰杯,因為大學生計算機設計大賽,很多比賽擺在面前但是我卻不知道怎么參加,不知道和誰一起參加,不知道自己的能力夠不夠參加,但是內心對于參賽這種經歷的渴望又在催促我去參加。自我的懷疑和對未知的渴望在我心中糾纏,好焦慮。唉,明天還是去找老師聊一聊伐。

總結

以上是生活随笔為你收集整理的蛮力法-分治法-处理最近对问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。