博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
旋转卡壳
阅读量:6544 次
发布时间:2019-06-24

本文共 6889 字,大约阅读时间需要 22 分钟。

4.1  求解平面最远点对(POJ 2187 Beauty Contest) struct Point {     int x,y;     Point(int _x = 0,int _y = 0)     {         x = _x; y = _y;     }     Point operator -(const Point &b)const     {         return Point(x - b.x, y - b.y);     }     int operator ^(const Point &b)const     {         return x*b.y - y*b.x;     }     int operator *(const Point &b)const     {         return x*b.x + y*b.y;     }     void input()     {         scanf("%d%d",&x,&y);     } }; //距离的平方 int dist2(Point a,Point b) {     return (a-b)*(a-b); } //******二维凸包,int*********** const int MAXN = 50010; Point list[MAXN]; int Stack[MAXN],top; bool _cmp(Point p1,Point p2) {     int tmp = (p1-list[0])^(p2-list[0]);     if(tmp > 0)return true;     else if(tmp == 0 && dist2(p1,list[0]) <= dist2(p2,list[0]))         return true;     else return false; } void Graham(int n) {     Point p0;     int k = 0;     p0 = list[0];     for(int i = 1;i < n;i++)         if(p0.y > list[i].y || (p0.y == list[i].y && p0.x > list[i].x))         {             p0 = list[i];             k = i;         }     swap(list[k],list[0]);     sort(list+1,list+n,_cmp);     if(n == 1)     {         top = 1;         Stack[0] = 0;         return;     }     if(n == 2)     {         top = 2;         Stack[0] = 0; Stack[1] = 1;         return;     }     Stack[0] = 0; Stack[1] = 1;     top = 2;     for(int i = 2;i < n;i++)     {         while(top > 1 && ((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)             top--;         Stack[top++] = i;     } } //旋转卡壳,求两点间距离平方的最大值 int rotating_calipers(Point p[],int n) {     int ans = 0;     Point v;     int cur = 1;     for(int i = 0;i < n;i++)     {         v = p[i]-p[(i+1)%n];         while((v^(p[(cur+1)%n]-p[cur])) < 0)             cur = (cur+1)%n;         ans = max(ans,max(dist2(p[i],p[cur]),dist2(p[(i+1)%n],p[(cur+1)%n])));      }     return ans; } Point p[MAXN]; int main() {     int n;     while(scanf("%d",&n) == 1)     {         for(int i = 0;i < n;i++)list[i].input();         Graham(n);         for(int i = 0;i < top;i++)p[i] = list[Stack[i]];         printf("%d\n",rotating_calipers(p,top));     }     return 0; } 4.2  求解平面点集最大三角形 //旋转卡壳计算平面点集最大三角形面积 int rotating_calipers(Point p[],int n) {     int ans = 0;     Point v;     for(int i = 0;i < n;i++)     {         int j = (i+1)%n;         int k = (j+1)%n;         while(j != i && k != i)         {             ans = max(ans,abs((p[j]-p[i])^(p[k]-p[i])));             while( ((p[i]-p[j])^(p[(k+1)%n]-p[k])) < 0 )                 k = (k+1)%n;             j = (j+1)%n;         }     }     return ans; } Point p[MAXN]; int main() {     int n;     while(scanf("%d",&n) == 1)     {         if(n == -1)break;         for(int i = 0;i < n;i++)list[i].input();         Graham(n);         for(int i = 0;i < top;i++)p[i] = list[Stack[i]];         printf("%.2f\n",(double)rotating_calipers(p,top)/2);     }     return 0; } 4.3  求解两凸包最小距离(POJ 3608) const double eps = 1e-8; int sgn(double x) {     if(fabs(x) < eps)return 0;     if(x < 0)return -1;     else return 1; } struct Point {     double x,y;     Point(double _x = 0,double _y = 0)     {         x = _x; y = _y;     }     Point operator -(const Point &b)const     {         return Point(x - b.x, y - b.y);     }     double operator ^(const Point &b)const     {         return x*b.y - y*b.x;     }     double operator *(const Point &b)const     {         return x*b.x + y*b.y;     }     void input()     {         scanf("%lf%lf",&x,&y);     } }; struct Line {     Point s,e;     Line(){}     Line(Point _s,Point _e)     {         s = _s; e = _e;     } }; //两点间距离 double dist(Point a,Point b) {     return sqrt((a-b)*(a-b)); } //点到线段的距离,返回点到线段最近的点 Point NearestPointToLineSeg(Point P,Line L) {     Point result;     double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));     if(t >=0 && t <= 1)     {         result.x = L.s.x + (L.e.x - L.s.x)*t;         result.y = L.s.y + (L.e.y - L.s.y)*t;     }     else     {         if(dist(P,L.s) < dist(P,L.e))             result = L.s;         else result = L.e;     }     return result; }  /*  * 求凸包,Graham算法  * 点的编号0~n-1  * 返回凸包结果Stack[0~top-1]为凸包的编号  */ const int MAXN = 10010; Point list[MAXN]; int Stack[MAXN],top; //相对于list[0]的极角排序 bool _cmp(Point p1,Point p2) {   double tmp = (p1-list[0])^(p2-list[0]);   if(sgn(tmp) > 0)return true;   else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0)     return true;   else return false; } void Graham(int n) {   Point p0;   int k = 0;   p0 = list[0];   //找最下边的一个点   for(int i = 1;i < n;i++)   {     if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )     {       p0 = list[i];       k = i;     }   }   swap(list[k],list[0]);   sort(list+1,list+n,_cmp);   if(n == 1)   {     top = 1;     Stack[0] = 0;     return;   }   if(n == 2)   {     top = 2;     Stack[0] = 0;     Stack[1] = 1;     return ;   }   Stack[0] = 0;   Stack[1] = 1;   top = 2;   for(int i = 2;i < n;i++)   {     while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)       top--;     Stack[top++] = i;   } } //点p0到线段p1p2的距离 double pointtoseg(Point p0,Point p1,Point p2) {     return dist(p0,NearestPointToLineSeg(p0,Line(p1,p2))); } //平行线段p0p1和p2p3的距离 double dispallseg(Point p0,Point p1,Point p2,Point p3) {     double ans1 = min(pointtoseg(p0,p2,p3),pointtoseg(p1,p2,p3));     double ans2 = min(pointtoseg(p2,p0,p1),pointtoseg(p3,p0,p1));     return min(ans1,ans2); } //得到向量a1a2和b1b2的位置关系 double Get_angle(Point a1,Point a2,Point b1,Point b2) {     return (a2-a1)^(b1-b2); } double rotating_calipers(Point p[],int np,Point q[],int nq) {     int sp = 0, sq = 0;     for(int i = 0;i < np;i++)         if(sgn(p[i].y - p[sp].y) < 0)             sp = i;     for(int i = 0;i < nq;i++)         if(sgn(q[i].y - q[sq].y) > 0)             sq = i;     double tmp;     double ans = dist(p[sp],q[sq]);     for(int i = 0;i < np;i++)     {         while(sgn(tmp = Get_angle(p[sp],p[(sp+1)%np],q[sq],q[(sq+1)%nq])) < 0)              sq = (sq+1)%nq;         if(sgn(tmp) == 0)             ans = min(ans,dispallseg(p[sp],p[(sp+1)%np],q[sq],q[(sq+1)%nq]));          else ans = min(ans,pointtoseg(q[sq],p[sp],p[(sp+1)%np]));         sp = (sp+1)%np;     }     return ans; } double solve(Point p[],int n,Point q[],int m) {     return min(rotating_calipers(p,n,q,m),rotating_calipers(q,m,p,n)); } Point p[MAXN],q[MAXN]; int main() {     int n,m;     while(scanf("%d%d",&n,&m) == 2)     {         if(n == 0 && m == 0)break;         for(int i = 0;i < n;i++)             list[i].input();         Graham(n);         for(int i = 0;i < top;i++)             p[i] = list[i];         n = top;         for(int i = 0;i < m;i++)             list[i].input();         Graham(m);         for(int i = 0;i < top;i++)             q[i] = list[i];         m = top;         printf("%.4f\n",solve(p,n,q,m));     }     return 0; }

转载于:https://www.cnblogs.com/xzxl/p/7247651.html

你可能感兴趣的文章
android app 退出时提示确认
查看>>
win10 配置
查看>>
java 编译100个范例
查看>>
Session Cookie ServletContext
查看>>
单点登录SSO
查看>>
遇见有的软件开启后画面模糊怎么解决
查看>>
好系统重装助手教你怎么识别固态硬盘还是机械硬盘
查看>>
170. js中获取随机数 (记录一下)
查看>>
深入浅出爬虫之道: Python、Golang与GraphQuery的对比
查看>>
DHCP配置
查看>>
MySQL性能测试(二)——Ubuntu 14.4.02, MySQL 5.6.25, sysbench 4.8
查看>>
我的友情链接
查看>>
网络安全十大注意
查看>>
cisco虚拟局域网VLAN路由----待补充
查看>>
join命令实现文件内容拼接
查看>>
-bash:wget command not found的解决方法
查看>>
yara规则
查看>>
我的个人简历
查看>>
我的友情链接
查看>>
我的友情链接
查看>>