zoukankan      html  css  js  c++  java
  • 算法作业1 3D最近点对问题

    算法思路:

    1. 数据预处理。先把点集中的所有点,按照Y坐标大小从左往右排序,得到关于Y轴的有序点集合。具体使用STL的qsort方法,自定义比较函数。
    2. 使用分治的思想, 把点集分开出来求解。先选取点集中Y坐标最中间的点,该点所在垂直于Y轴的平面把点集划分成两个子点集leftSubSet和rightSubSet,然后分别计算两个子点集中最短的点对。以此类推,分到子点集仅包含3个点以下。当子点集小于等于3个点时,使用暴力遍历法求解这些点对的最短距离。
    3. “分”求出leftSubSet和rightSubSet的最短距离currentMin后,“治”的方法是,把Y坐标与切平面的距离小于currentMin的点取出,分成l_middle和r_middle。因为只有这些点才有可能构成两个子点集的最短距离点对。接着对l_middle中的每一个点来说,只有与r_middle中点的X坐标和Z坐标小于currentMin的点才有可能是最短距离点。分别计算他们的欧几里得距离,将距离最小的点对记录下来,更新currentMin。
    4. 为了能找出所有最短距离相等的点对,这里使用了一个stack全局变量把最短距离点对存储起来,每次计算出比stack中的点对距离还要小的点对时,把stack清空,把新点对压进stack。如果距离一样,则继续往stack中放。

    代码实现:

      1 #include<iostream>
      2 #include<stack>
      3 #include<vector>
      4 #include<time.h>
      5 #define maxn 100
      6 using namespace std;
      7 
      8 struct Point{
      9     double x;
     10     double y;
     11     double z;
     12 }dataset[maxn];
     13 
     14 stack<Point> resultpairs;
     15 
     16 int cmp(const void *a, const void *b){
     17     return ((Point *)a)->y - ((Point *)b)->y;
     18 }
     19 
     20 double Distance(const Point &p1, const Point &p2){
     21     return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z));
     22 }
     23 
     24 double findMinDistance(int left_m, int right_m, int n){
     25     double minDistance = INT_MAX;
     26 
     27     //小于等于3个点时暴力解决求出最短距离
     28     if(n <= 3){
     29         for (int i = left_m; i <= right_m; i++){
     30             for (int j = i + 1; j <= right_m; j++){
     31                 if(Distance(dataset[i], dataset[j]) <= minDistance){
     32                     minDistance = Distance(dataset[i], dataset[j]);
     33 
     34                     //把距离最小的点压栈到resultpairs
     35                     if(!resultpairs.empty()){
     36                         Point t1 = resultpairs.top();
     37                         resultpairs.pop();
     38                         Point t2 = resultpairs.top();
     39                         resultpairs.pop();
     40 
     41                         double now = Distance(t1, t2);
     42                         if(minDistance < now){
     43                             while(!resultpairs.empty())resultpairs.pop();
     44                             resultpairs.push(dataset[i]);
     45                             resultpairs.push(dataset[j]);
     46                         }
     47                         else {
     48                             resultpairs.push(t2);
     49                             resultpairs.push(t1);
     50                             if(minDistance == now){
     51                                 resultpairs.push(dataset[i]);
     52                                 resultpairs.push(dataset[j]);
     53                             }
     54                         }
     55                     }
     56                     else{
     57                         resultpairs.push(dataset[i]);
     58                         resultpairs.push(dataset[j]);
     59                     }
     60                 }
     61             }
     62         }
     63         return minDistance;
     64     }
     65     else{
     66 
     67         //找到在Y轴看最中间的点,记下其Y坐标,把点集分成两堆pL和pR。
     68         int middle = (left_m + right_m) / 2;
     69         double middleY = dataset[middle].y;
     70 
     71         //分而治之
     72         //找到两边最小的点对,把距离放进currentMinDistance
     73         double lMinDistance = findMinDistance(left_m, middle, middle - left_m + 1);
     74         double rMinDistance = findMinDistance(middle + 1, right_m, right_m - middle);
     75         double currentMinDistance = lMinDistance < rMinDistance ? lMinDistance: rMinDistance;
     76 
     77         //找出所有分居切面两边,且两两之间有可能成为最小距离的点放进middleP,它们的Y坐标放进middleArrayY
     78         vector<Point> l_middle_Points;
     79         vector<Point> r_middle_Points;
     80         for(int i = left_m; i <= right_m; i++){
     81             if((i <= middle) && (middleY - dataset[i].y <= currentMinDistance)){
     82                 l_middle_Points.push_back(dataset[i]);
     83             }
     84             if((i > middle) && (dataset[i].y - middleY <= currentMinDistance)){
     85                 r_middle_Points.push_back(dataset[i]);
     86             }
     87         }
     88 
     89         vector<Point>::iterator end = l_middle_Points.end();
     90         vector<Point>::iterator end2 = r_middle_Points.end();
     91 
     92         double newdis = INT_MAX;
     93         for(vector<Point>::iterator it = l_middle_Points.begin(); it != end; ++it){
     94             for(vector<Point>::iterator it2 = r_middle_Points.begin(); it2 != end2; ++it2){
     95 
     96                 if((fabs(it->x - it2->x) <= currentMinDistance) && (fabs(it->z - it2->z) <= currentMinDistance)){
     97                     newdis = Distance(*it, *it2);
     98                     if(newdis <= currentMinDistance){
     99                         currentMinDistance = newdis;
    100                         if(!resultpairs.empty()){
    101                             Point t1 = resultpairs.top();
    102                             resultpairs.pop();
    103                             Point t2 = resultpairs.top();
    104                             resultpairs.pop();
    105 
    106                             double now = Distance(t1, t2);
    107                             if(newdis < now){
    108                                 while(!resultpairs.empty())resultpairs.pop();
    109                                 resultpairs.push(*it);
    110                                 resultpairs.push(*it2);
    111                             }
    112                             else {
    113                                 resultpairs.push(t2);
    114                                 resultpairs.push(t1);
    115                                 if(newdis == now){
    116                                     resultpairs.push(*it);
    117                                     resultpairs.push(*it2);
    118                                 }
    119                             }
    120                         }
    121                         else{
    122                             resultpairs.push(*it);
    123                             resultpairs.push(*it2);
    124                         }
    125                     }
    126                 }
    127             }
    128         }
    129         minDistance = currentMinDistance;
    130         return minDistance;
    131     }
    132 }
    133 
    134 int main(){
    135 
    136     //把标准输入重定向到文件输入
    137     freopen("dataout.txt","r",stdin);  
    138 
    139     //记录程序运行时间
    140     clock_t start,finish;  
    141     double totaltime;  
    142     start=clock();  
    143 
    144     //数据读取
    145     for(int i = 0; i < maxn; i++){
    146         cin >> dataset[i].x;
    147         cin >> dataset[i].y;
    148         cin >> dataset[i].z;
    149     }
    150 
    151     //快速排序点集
    152     qsort(dataset, maxn, sizeof(dataset[0]), cmp);
    153 
    154     //查找最短距离,并将所有距离相等的点对压入resultpairs
    155     double mindis = findMinDistance(0, maxn - 1, maxn);
    156 
    157     cout<<"shortest distance is: "<<mindis<<endl;
    158     cout<<"
    all closest pairs are: "<<endl;
    159     
    160     Point a;
    161     while(!resultpairs.empty()) {
    162         a = resultpairs.top();
    163         cout << "(" << a.x <<", " <<a.y<<", "<<a.z<<") and ";
    164         resultpairs.pop();
    165         a = resultpairs.top();
    166         cout << "(" << a.x <<", " <<a.y<<", "<<a.z<<")"<<endl;
    167         resultpairs.pop();
    168     }
    169 
    170 
    171     finish=clock();  
    172     totaltime=(double)(finish-start)/CLOCKS_PER_SEC;  
    173     cout<<"
    it runs "<<totaltime<<" seconds!"<<endl; 
    174     return 0;  
    175 }
    View Code
  • 相关阅读:
    bzoj3751 / P2312 解方程
    P1270 “访问”美术馆(树形dp)
    [bzoj1085][SCOI2005]骑士精神
    [bzoj1208][HNOI2004]宠物收养所
    [bzoj1196][HNOI2006]公路修建问题
    [bzoj1093][ZJOI2007]最大半连通子图
    [bzoj1103][POI2007]大都市meg
    [Apio2009][bzoj1179]Atm
    [bzoj1191][HNOI2006]超级英雄Hero
    [bzoj2458][BeiJing2011]最小三角形
  • 原文地址:https://www.cnblogs.com/banyu/p/4951522.html
Copyright © 2011-2022 走看看