求两个凸包间的最小距离,最大距离,都是用同一种思路
最大距离:枚举凸包A的每条边,然后去B找对踵点,求的是点到点的最短距离
最小距离:比最大距离稍复杂一点,枚举凸包A的每条边,去B找对踵点,如果只有一个对踵点,那么求点到线段最短距离
如果有两个对踵点,那么求线段到线段的最短距离(需要改动一下disSS函数)
poj上的c++和G++是不一样的。。
disSS函数不用判线段相交了
db disSS(point k1,point k2,point k3,point k4){ return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2))); }
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> using namespace std; typedef double db; const db eps=1e-8; const db pi=acos(-1.0); int sign(db k){ if (k>eps) return 1; else if (k<-eps) return -1; return 0; } int cmp(db k1,db k2){return sign(k1-k2);} int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 struct point{ db x,y; point(){} point(db x,db y):x(x),y(y){} point operator + (const point &k1) const{return point(k1.x+x,k1.y+y);} point operator - (const point &k1) const{return point(x-k1.x,y-k1.y);} point operator * (db k1) const{return point(x*k1,y*k1);} point operator / (db k1) const{return point(x/k1,y/k1);} bool operator < (const point k1) const{ int a=cmp(x,k1.x); if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1; } db abs(){return sqrt(x*x+y*y);} db abs2(){return x*x+y*y;} db dis(point k1){return ((*this)-k1).abs();} }; int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);} db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2()); } int intersect(db l1,db r1,db l2,db r2){ if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1; } int checkSS(point k1,point k2,point k3,point k4){ return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&& sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&& sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0; } db disSP(point k1,point k2,point q){ point k3=proj(k1,k2,q); if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2)); } db disSS(point k1,point k2,point k3,point k4){ return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2))); } int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;} int checkconvex(vector<point>A){ //判断是否是凸包 int n=A.size(); A.push_back(A[0]); A.push_back(A[1]); for (int i=0;i<n;i++) if (sign(cross(A[i+1]-A[i],A[i+2]-A[i]))==-1) return 0; return 1; } vector<point> ConvexHull(vector<point>A,int flag=1){ // 求凸包:flag=0 不严格 flag=1 严格 int n=A.size(); vector<point>ans(n*2); sort(A.begin(),A.end()); int now=-1; for (int i=0;i<A.size();i++){ while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--; ans[++now]=A[i]; } int pre=now; for (int i=n-2;i>=0;i--){ while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--; ans[++now]=A[i]; } ans.resize(now); return ans; } db ConvexMinDis(vector<point> a,vector<point> b){ db Min=1e16; a.push_back(a[0]);b.push_back(b[0]); db ymin=1e16,ymax=-1e16; int p,q; for(int i=0;i<a.size()-1;i++) if(a[i].y<ymin)ymin=a[i].y,p=i; for(int i=0;i<b.size()-1;i++) if(b[i].y>ymax)ymax=b[i].y,q=i; db tmp; for(int i=0;i<a.size()-1;i++){//枚举a凸包上的边(p,p+1),比较b凸包上点q,q+1 while(sign(tmp=cross(a[p+1]-a[p],b[q+1]-a[p])-cross(a[p+1]-a[p],b[q]-a[p]))>0){ q++; if(q==b.size()-1)q=0; } if(sign(tmp)<0)Min=min(Min,disSP(a[p],a[p+1],b[q]));//点到线段的距离 else Min=min(Min,disSS(a[p],a[p+1],b[q],b[q+1]));//线段到线段的距离 p++; if(p==a.size()-1)p=0; } return Min; } int n,m; vector<point> v1,v2; int main(){ while(cin>>n>>m && n && m){ v1.clear(); v2.clear(); for(int i=1;i<=n;i++){ point p; scanf("%lf%lf",&p.x,&p.y); v1.push_back(p); } for(int i=1;i<=m;i++){ point p; scanf("%lf%lf",&p.x,&p.y); v2.push_back(p); } vector<point>con1=ConvexHull(v1,1); vector<point>con2=ConvexHull(v2,1); printf("%.5f ",min(ConvexMinDis(con1,con2),ConvexMinDis(con2,con1))); } } /* 2.00000 322.91330 132.00758 229.96087 220.29299 285.24551 228.88643 265.17353 273.54159 278.82073 160.05624 283.06360 204.36487 234.82973 325.35826 2.00000 320.62439 130.09612 228.26520 217.84857 282.70479 228.35499 264.06817 271.83083 277.00181 157.19097 281.32543 202.27704 233.45235 323.73600 322.91330 320.62439 127.28162 48.15016 75.91705 7.00000 147.00000 147.13939 88.09830 18.00000 102.39141 75.00000 95.70789 86.02325 4.00000 132.00758 130.09612 127.28162 25.80698 24.36311 88.20431 56.32051 79.83107 69.40461 75.66373 25.15538 79.02531 5.77843 39.70142 121.43311 229.96087 228.26520 48.15016 25.80698 8.77678 25.67736 45.27693 65.36819 25.80603 12.00000 41.00000 29.18802 6.15651 7.42567 53.30219 220.29299 217.84857 75.91705 24.36311 8.77678 20.94556 124.19742 143.69016 91.78780 77.00000 19.00000 93.62149 31.39963 74.33034 112.09107 285.24551 282.70479 7.00000 88.20431 25.67736 20.94556 127.73801 134.73678 72.73239 20.00000 46.23851 62.76942 72.57472 65.19202 38.00000 228.88643 228.35499 147.00000 56.32051 45.27693 124.19742 127.73801 16.26346 41.71930 70.00714 159.76232 65.49046 64.40497 4.28413 92.35800 265.17353 264.06817 147.13939 79.83107 65.36819 143.69016 134.73678 16.26346 13.43503 75.27284 180.60177 67.91171 85.42248 6.27208 76.11833 273.54159 271.83083 88.09830 69.40461 25.80603 91.78780 72.73239 41.71930 13.43503 13.34166 134.25705 7.24416 51.47815 6.36396 7.00000 278.82073 277.00181 18.00000 75.66373 12.00000 77.00000 20.00000 70.00714 75.27284 13.34166 113.00000 7.96960 52.00000 16.68474 18.52915 160.05624 157.19097 102.39141 25.15538 41.00000 19.00000 46.23851 159.76232 180.60177 134.25705 113.00000 135.77085 68.39894 116.42048 137.87676 283.06360 281.32543 75.00000 79.02531 29.18802 93.62149 62.76942 65.49046 67.91171 7.24416 7.96960 135.77085 58.94065 18.91277 32.18925 204.36487 202.27704 95.70789 5.77843 6.15651 31.39963 72.57472 64.40497 85.42248 51.47815 52.00000 68.39894 58.94065 33.39838 103.12502 234.82973 233.45235 86.02325 39.70142 7.42567 74.33034 65.19202 4.28413 6.27208 6.36396 16.68474 116.42048 18.91277 33.39838 56.41515 325.35826 323.73600 4.00000 121.43311 53.30219 112.09107 38.00000 92.35800 76.11833 7.00000 18.52915 137.87676 32.18925 103.12502 56.41515 */
数据生成
#include <stdio.h> struct point{double x,y;}; struct polygon { int n; point data[10]; }; #define N 16 polygon p[N]={ {4,{{0,0},{-1,0},{-1,-1},{0,-1}}}, {4,{{2,0},{2,-1},{3,-1},{3,0}}}, {4,{{247,208},{247,235},{375,235},{375,208}}}, {3,{{85 ,101},{116 ,168},{168 ,103}}}, {3,{{131 ,189},{216 ,148},{196 ,209}}}, {3,{{180 ,127},{246 ,127},{202 ,144}}}, {3,{{226 ,201},{297 ,201},{242 ,151}}}, {3,{{42 ,225},{61 ,261},{100,222}}}, {3,{{84 ,261},{99 ,246},{102,260}}}, {3,{{72,309},{157,224},{167,309}}}, {3,{{170,221},{229,221},{199,245}}}, {3,{{190,90},{153,47},{225,108}}}, {3,{{165,230},{168,242},{172,233}}}, {6,{{143,146},{133,156},{138,170},{150,173},{161,166},{161,152}}}, {5,{{109,208},{100,236},{111,253},{122,250},{161,206}}}, {6,{{177,273},{174,309},{202,377},{417,375},{490,270},{268,239}}} }; int main() { //freopen("C:\Documents and Settings\Administrator\桌面\out.txt","w",stdout); int i,j,k,num=0; for(i=0;i<N;i++) { for(j=0;j<N;j++) { if(i==j) continue; num++; //if(num>35||num<=33)continue; printf("%d %d ",p[i].n,p[j].n); for(k=0;k<p[i].n;k++) printf("%lf %lf ",p[i].data[k].x,p[i].data[k].y); for(k=0;k<p[j].n;k++) printf("%lf %lf ",p[j].data[k].x,p[j].data[k].y); printf(" "); } } printf("0 0 "); return 0; }