计算几何
先给自己留几个模板,估计考试的时候也不一定能写出来,今天见到了一个题,求平面上的最远点对和最近点对
最远点对一定在凸包上,可以求出凸包后用旋转卡壳来写,一般的求出后直接枚举就行了,用的是Graham -Scan水平序写法,
http://hi.baidu.com/pianoeater/item/03ddb1868a71f003c316279b
http://blog.csdn.net/cjoilmd/article/details/7169420
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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