计算几何

先给自己留几个模板,估计考试的时候也不一定能写出来,今天见到了一个题,求平面上的最远点对和最近点对

 

最远点对一定在凸包上,可以求出凸包后用旋转卡壳来写,一般的求出后直接枚举就行了,用的是Graham -Scan水平序写法,

http://hi.baidu.com/pianoeater/item/03ddb1868a71f003c316279b

http://blog.csdn.net/cjoilmd/article/details/7169420

 

View Code
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 using namespace std;
  6 const int M=100005;
  7 typedef struct Point
  8 {
  9 double x;
 10 double y;
 11 }Point;
 12 Point p[M];
 13 Point pp[M];
 14 bool bo[M];
 15 int stack[M];//form 1 to t;
 16 double dis(Point A,Point B)
 17 {
 18 return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
 19 }
 20 bool cmp(Point a,Point b)
 21 {
 22 if(a.x<b.x)
 23     return true;
 24 if(a.x>b.x)
 25     return false;
 26 if(a.y<b.y)
 27     return true;
 28 return false;
 29 }
 30 double Xdet(Point A,Point B,Point C)
 31 {
 32 double x1,x2,y1,y2;
 33 x1=B.x-A.x;
 34 y1=B.y-A.y;
 35 x2=C.x-A.x;
 36 y2=C.y-A.y;
 37 return x1*y2-x2*y1;//大于0在左手边,逆时针
 38 }
 39 //把点集凸包化Gram_Scan算法(使用水平序)
 40 void Gram_Scan(Point *p,int &n)//p从1-n,把点集凸包化
 41 {
 42 int i,t;
 43 sort(p+1,p+1+n,cmp);
 44 //去重
 45 for(t=0,i=1;i<=n;i++)
 46 {
 47     if(i>1&&p[i].x==p[i-1].x&&p[i].y==p[i-1].y)
 48       continue;
 49     p[++t]=p[i];
 50 }
 51 n=t;
 52 t=0;
 53 memset(bo+1,true,n*sizeof(bo[0]));
 54 if(n>0)
 55 {
 56     stack[++t]=1;
 57     bo[stack[t]]=false;
 58 }
 59 if(n>1)
 60 {
 61     stack[++t]=2;
 62     bo[stack[t]]=false;
 63 }
 64 if(n>2)
 65 {
 66     for(i=3;i<n;i++)
 67       if(bo[i]&&Xdet(p[stack[t-1]],p[stack[t]],p[i])>=0)
 68       {
 69         stack[++t]=i;
 70         bo[i]=false;
 71       }
 72       else
 73       {
 74         while(t>=2&&Xdet(p[stack[t-1]],p[stack[t]],p[i])<0)
 75         {
 76           bo[stack[t]]=true;
 77           t--;
 78         }
 79         stack[++t]=i;
 80         bo[stack[t]]=false;
 81       }
 82    for(i=n;i>=1;i--)
 83      if(bo[i]&&Xdet(p[stack[t-1]],p[stack[t]],p[i])>=0)
 84      {
 85        stack[++t]=i;
 86        bo[i]=false;
 87      }
 88      else
 89      {
 90        while(t>=2&&Xdet(p[stack[t-1]],p[stack[t]],p[i])<0)
 91        {
 92          bo[stack[t]]=true;
 93          t--;
 94        }
 95        stack[++t]=i;
 96        bo[stack[t]]=false;
 97      }
 98      t--;
 99 }
100 for(i=1;i<=t;i++)
101     pp[i]=p[stack[i]];
102 memcpy(p+1,pp+1,t*sizeof(Point));
103 n=t;
104 }
105 int n,o[M],on;
106 int dcmp(double a,double b)
107 {
108     if(a-b<1e-10&&b-a<1e-10)
109         return 0;
110     if(a>b)
111         return 1;
112     return -1;
113 }
114 bool cmp1(Point a,Point b)
115 {
116     return dcmp(a.x,b.x)<0;
117 }
118 bool cmp2(int a,int b)
119 {
120     return dcmp(p[a].y,p[b].y)<0;
121 }
122 double min(double a,double b)
123 {
124     return a<b?a:b;
125 }
126 double search(int s,int t)
127 {
128     int mid=(s+t)/2,i,j;
129     double ret=1e300;
130     if(s>=t)
131         return ret;
132     for(i=mid;i>=s&&!dcmp(p[i].x,p[mid].x);i--);
133     ret=search(s,i);
134     for(i=mid;i<=t&&!dcmp(p[i].x,p[mid].x);i++);
135     ret=min(ret,search(i,t));on=0;
136     for(i=mid;i>=s&&dcmp(p[mid].x-p[i].x,ret)<=0;i--)
137         o[++on]=i;
138     for(i=mid+1;i<=t&&dcmp(p[i].x-p[mid].x,ret)<=0;i++)
139         o[++on]=i;
140     sort(o+1,o+on+1,cmp2);
141     for(i=1;i<=on;i++)
142         for(j=1;j<=10;j++)
143             if(i+j<=on)
144                 ret=min(ret,dis(p[o[i]],p[o[i+j]]));
145     return ret;
146 }
147 int main()
148 {
149     freopen("postmanb.in","r",stdin);
150     freopen("postmanb.out","w",stdout);
151     
152     int n,i,count=0,j;
153     double shortdis,longdis;
154     scanf("%d",&n);
155         for(i=1;i<=n;i++)
156             scanf("%lf%lf",&p[i].x,&p[i].y);
157         sort(p+1,p+n+1,cmp1);
158         shortdis=search(1,n);
159         longdis=0;
160         Gram_Scan(p,n);
161         for(i=1;i<=n-1;i++)
162             for(j=i+1;j<=n;j++)
163                 if(dis(p[i],p[j])>longdis)
164                     longdis=dis(p[i],p[j]);
165         printf("%.3lf\n",longdis);
166         printf("%.3lf\n",shortdis);    
167     fclose(stdin);fclose(stdout);
168     return 0;
169 }

 

最近点对用的就是分治的方法了、

http://blog.csdn.net/bertzhang/article/details/7260509

http://www.cnblogs.com/sleeper-qp/archive/2011/11/08/2241004.html

posted @ 2012-07-17 14:47  守護N1身边  阅读(146)  评论(0编辑  收藏  举报