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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

分治应用--最近点对问题 POJ 3714

發布時間:2024/7/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分治应用--最近点对问题 POJ 3714 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1. 問題描述
    • 2. 解題思路
    • 3. 實現代碼
    • 4. POJ 3714

1. 問題描述

二維平面上有n個點,如何快速計算出兩個距離最近的點對?

2. 解題思路

  • 暴力做法是,每個點與其他點去計算距離,取最小的出來,復雜度O(n2)
  • 采用分治算法
  • 將數據點按照 x 坐標排序,找到中位點,過中位點劃線 x = mid_x 將數據分成2部分,遞歸劃分,直到兩個半邊只有1個或者2個數據,只有1個數據點,最短距離返回無窮大,有2個點直接返回2點的距離
  • 合并左右兩邊的結果,取左右兩邊的最短距離的較小值為 d = min{dl,dr},那么在 x = mid_x 的 ± d 范圍內的左右點對才有可能距離比 d 更小(好理解)
  • 對這個范圍內的點,再按照 y 坐標排序,查找兩個點的 y 差值小于 d 的點對(重點在這里,見下面分析),計算其距離是否比 d 更小

    假如在這個范圍內的有1,2,3,4,5,6六個點(按 y 坐標排序),尋找距離小于 d 的點對,如果暴力查找,復雜度還是 n2,我們可以看出點4只有可能在其上下y坐標 ± d 的范圍內找到滿足距離小于 d 的點匹配,點1和點4不可能距離小于 d,左邊的點最多可以有4個右邊的點使得其距離小于 d

    所以,步驟3是O(n)復雜度。
    T(1) = 1;T(n) = 2*T(n/2)+n;高中數學即可求得T(n)是O(nlogn)的復雜度。
  • 3. 實現代碼

    /*** @description: 2維平面尋找距離最近的點對(分治)* @author: michael ming* @date: 2019/7/4 23:16* @modified by: */ #include <iostream> #include <cmath> #include <vector> #include <ctime> #include <algorithm> #define LEFT_BOUND 0.0 #define RIGHT_BOUND 100.0 #define LOWER_BOUND 0.0 #define UPPER_BOUND 100.0 //隨機點的范圍 using namespace std; class Point//點 { public:int id;double x, y;Point(int index, double x0, double y0):id(index),x(x0),y(y0){} }; typedef vector<Point> PointVec; bool compx(const Point &a, const Point &b) {if(a.x != b.x)return a.x < b.x;return a.y < b.y; } bool compy(const Point &a, const Point &b) {return a.y < b.y; }class ClosestPoint {PointVec points_vec;int numOfPoint; public:ClosestPoint(){srand(unsigned(time(0)));double x, y;cout << "請輸入測試點個數,將隨機生成散點:";cin >> numOfPoint;for(int i = 0; i < numOfPoint; ++i){x = LEFT_BOUND + (double)rand()/RAND_MAX *(RIGHT_BOUND-LEFT_BOUND);y = LOWER_BOUND + (double)rand()/RAND_MAX *(UPPER_BOUND-LOWER_BOUND);cout << i+1 << " (" << x << "," << y << ")" << endl;points_vec.emplace_back(i+1,x,y);//生成點的動態數組}}double dist(const Point &a, const Point &b){double dx = a.x - b.x;double dy = a.y - b.y;return sqrt(dx*dx + dy*dy);//返回兩點之間的距離}void bfCalDist()//暴力求解{size_t num = points_vec.size();if(num <= 1){cout << "輸入個數<=1 !!!" << endl;return;}int i, j, s, t;double distance = RAND_MAX, d;for(i = 0; i < num; ++i)for(j = i+1; j < num; ++j){d = dist(points_vec[i], points_vec[j]);if(d < distance){distance = d;s = points_vec[i].id;t = points_vec[j].id;}}cout << "點" << s << "到點" << t << "的距離最小:" << distance << endl;}double calcDist(size_t left, size_t right, size_t &s, size_t &t){if(left == right)//一個點,返回無窮大return RAND_MAX;if(left+1 == right)//兩個點,直接計算距離{s = points_vec[left].id;t = points_vec[right].id;return dist(points_vec[left],points_vec[right]);}sort(points_vec.begin()+left,points_vec.begin()+right+1,compx);//把點群按照x排序size_t mid = (left+right)/2;double mid_x = points_vec[mid].x;double distance = RAND_MAX, d;distance = min(distance,calcDist(left,mid,s,t));//遞歸劃分左邊distance = min(distance,calcDist(mid+1,right,s,t));//遞歸劃分右邊size_t i, j, k = 0;PointVec temp;//存儲臨時點(在mid_x左右d范圍內的)for(i = left; i <= right; ++i){if(fabs(points_vec[i].x-mid_x) <= distance){temp.emplace_back(points_vec[i].id,points_vec[i].x,points_vec[i].y);k++;}}sort(temp.begin(),temp.end(),compy);//再把范圍內的點,按y排序for(i = 0; i < k; ++i){for(j = i+1; j < k && temp[j].y-temp[i].y < distance; ++j){//在臨時點里尋找距離更小的,內層循環最多執行不超過4次就會退出d = dist(temp[i],temp[j]);if(d < distance){distance = d;s = temp[i].id;t = temp[j].id;}}}return distance;}void closestDist()//調用分治求解{size_t num = points_vec.size();if(num <= 1){cout << "輸入個數<=1 !!!" << endl;return;}size_t s, t; s = t = 0;//記錄起終點double d = calcDist(0,num-1,s,t);cout << "點" << s << "到點" << t << "的距離最小:" << d << endl;}}; int main() {ClosestPoint cp;clock_t start, end;cout << "方法1,暴力求解:" << endl;start = clock();cp.bfCalDist();end = clock();cout << "耗時:" << (double)(end - start) << "ms." << endl;cout << "-------------------" << endl;cout << "方法2,分治求解:" << endl;start = clock();cp.closestDist();end = clock();cout << "耗時:" << (double)(end - start) << "ms." << endl;return 0; }

    4. POJ 3714

    http://poj.org/problem?id=3714
    相同的問題,只是數據位置分為2類(人,核電站),計算距離時,需判斷是不同的類,否則返回一個很大的數。

    以下代碼顯示Wrong Answer,誰幫忙看下。測試樣例輸出是一樣的。

    /*** @description: poj3714求解最近的核電站距離* @author: michael ming* @date: 2019/7/6 0:09* @modified by: */ #include<iomanip> #include <iostream> #include <cmath> #include <vector> #include <algorithm> #define DBL_MAX 1.7976931348623158e+308 using namespace std; class Point//點 { public:int id;int x, y;Point(int index, int x0, int y0):id(index),x(x0),y(y0){} }; typedef vector<Point> PointVec; bool compx(const Point &a, const Point &b) {if(a.x != b.x)return a.x < b.x;return a.y < b.y; } bool compy(const Point &a, const Point &b) {return a.y < b.y; }class ClosestPoint {PointVec points_vec;int numOfPoint; public:ClosestPoint(){int x, y;cin >> numOfPoint;for(int i = 0; i < numOfPoint; ++i){cin >> x >> y;points_vec.push_back(Point(0,x,y));//生成站點的動態數組(0表示站)}for(int i = 0; i < numOfPoint; ++i){cin >> x >> y;points_vec.push_back(Point(1,x,y));//加入人的位置(1表示人)}}double dist(const Point &a, const Point &b){if(a.id == b.id)return DBL_MAX;//相同的類型,返回很大的數int dx = a.x - b.x;int dy = a.y - b.y;return sqrt(double(dx*dx + dy*dy));//返回兩點之間的距離}double calcDist(size_t left, size_t right){if(left == right)//一個點,返回無窮大return DBL_MAX;if(left+1 == right)//兩個點,直接計算距離{return dist(points_vec[left],points_vec[right]);}sort(points_vec.begin()+left,points_vec.begin()+right+1,compx);//把點群按照x排序size_t mid = (left+right)/2;double mid_x = points_vec[mid].x;double distance = DBL_MAX, d;distance = min(distance,calcDist(left,mid));//遞歸劃分左邊distance = min(distance,calcDist(mid+1,right));//遞歸劃分右邊size_t i, j, k = 0;PointVec temp;//存儲臨時點(在mid_x左右d范圍內的)for(i = left; i <= right; ++i){if(fabs(points_vec[i].x-mid_x) <= distance){temp.push_back(Point(points_vec[i].id,points_vec[i].x,points_vec[i].y));k++;}}sort(temp.begin(),temp.end(),compy);//再把范圍內的點,按y排序for(i = 0; i < k; ++i){for(j = i+1; j < k && temp[j].y-temp[i].y <= distance; ++j){//在臨時點里尋找距離更小的,內層循環最多執行不超過4次就會退出d = dist(temp[i],temp[j]);if(d < distance){distance = d;}}}return distance;}double closestDist()//調用分治求解{size_t num = points_vec.size();return calcDist(0,num-1);}}; int main() {int times;cin >> times;while (times--){ClosestPoint cp;cout << fixed << setprecision(3) << cp.closestDist() << endl;}return 0; }

    總結

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

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

    主站蜘蛛池模板: 天天看天天做 | 污视频在线观看网站 | 亚欧日韩 | 久久理伦 | 小明天天看 | 欧美不卡一区二区三区 | 日剧网| 亚洲精品乱码久久久久久写真 | 诱惑av | 使劲插视频 | 婷婷五月精品中文字幕 | 97青草| 免费av观看| 五月综合在线 | 精品国产一二 | 偷偷操av| 性做久久久久久久免费看 | 人妻中文字幕一区二区三区 | 亚洲在线一区二区 | www.com国产 | 91丨九色丨黑人外教 | aaa在线| 久久激情综合网 | 天天插天天操天天干 | 国内精品视频一区二区三区 | 国产区福利| 亚洲精选一区二区 | 日韩av一区在线观看 | 成人传媒| 深夜老司机福利 | 欧美日韩三区 | 无码精品一区二区三区AV | 成年网站免费在线观看 | h在线免费| 国产在线高潮 | 黄色三级视频 | 亚洲草逼 | 黑人操中国女人视频 | 免费成人av在线 | 饥渴的少妇和男按摩师 | 欧美日韩中文视频 | 五月天综合激情网 | 亚洲一区二区三区色 | av毛片网| 丰满人妻综合一区二区三区 | 五月婷在线观看 | 99热这里只有精 | 扒开腿揉捏花蒂h | 国产视频精品一区二区三区 | 亚洲最大的成人网 | 国产伦精品一区二区三区照片91 | 欧美bdsm调教视频 | 亚洲男人在线 | 免费日本特黄 | 亚洲三级欧美 | 波多野结衣激情视频 | 少妇无套内谢免费视频 | 日本不卡一区二区 | 借种(出轨高h)| 欧美精品乱人伦久久久久久 | 夜夜草天天干 | 国产精品久久婷婷 | 亚洲精品国产精品国自产观看浪潮 | 免费黄色视屏 | 精品一区二区三区成人免费视频 | 天天综合网在线观看 | 打屁股疼的撕心裂肺的视频 | 亚洲啪av永久无码精品放毛片 | 久久久五月 | 中文字幕精品久久久久人妻红杏ⅰ | 91黄色在线观看 | 久久综合加勒比 | 日日插夜夜爽 | 久草中文在线观看 | 精品裸体舞一区二区三区 | 日本午夜一区二区 | 国产精品第一国产精品 | 综合色站导航 | 91亚洲国产成人精品一区二三 | 国产男人搡女人免费视频 | 日韩激情在线视频 | 天天射天天色天天干 | 久啪视频 | www.桃色| 成人自拍视频在线 | 黄色片毛片 | 国产香蕉一区 | 日本变态折磨凌虐bdsm在线 | 国产又粗又猛视频免费 | 久久精品波多野结衣 | 韩国精品久久久 | 国产免费又爽又色又粗视频 | 亚洲美女视频网站 | 在线观看日本视频 | 欧美碰碰碰 | 日韩欧美资源 | 日本色一区 | 黄色a一级 | 国产又粗又猛又色又 |