Codeforces Gym - 101635K Blowing Candles [旋转卡壳]
2017-12-17 14:16
393 查看
题意:给你平面上n个点,求用最短的线段平移覆盖所有的点。
题解:既然线段能覆盖所有的点,那么可以知道是两条平行线之间包含所有的点,其实就是找凸包上的对踵点对。
对踵点对:对于多边形来说,如果两个点 p 和 q (属于 P) 在两条平行切线上, 那么他们就形成了一个对踵点对。
易得:最近的一对平行线,一定包含多边形的一条边,于是我们可以通过旋转卡壳,求出所有对踵点对,然后求点到直线的距离的最小值,就可以得到答案。
AC代码:
题解:既然线段能覆盖所有的点,那么可以知道是两条平行线之间包含所有的点,其实就是找凸包上的对踵点对。
对踵点对:对于多边形来说,如果两个点 p 和 q (属于 P) 在两条平行切线上, 那么他们就形成了一个对踵点对。
易得:最近的一对平行线,一定包含多边形的一条边,于是我们可以通过旋转卡壳,求出所有对踵点对,然后求点到直线的距离的最小值,就可以得到答案。
AC代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #define INF 9999999999999.9 #define PI acos(-1.0) struct Point { double x, y, dis; }pt[200005], stack[200005], p0; int top, tot; //计算几何距离 double Dis(double x1, double y1, double x2, double y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } //极角比较, 返回-1: p0p1在p0p2的右侧,返回0:p0,p1,p2共线 int Cmp_PolarAngel(struct Point p1, struct Point p2, struct Point pb) { double delta=(p1.x-pb.x)*(p2.y-pb.y)-(p2.x-pb.x)*(p1.y-pb.y); if (delta<0.0) return 1; else if (delta==0.0) return 0; else return -1; } // 判断向量p2p3是否对p1p2构成左旋 bool Is_LeftTurn(struct Point p3, struct Point p2, struct Point p1) { int type=Cmp_PolarAngel(p3, p1, p2); if (type<0) return true; return false; } //先按极角排,再按距离由小到大排 int Cmp(const void*p1, const void*p2) { struct Point*a1=(struct Point*)p1; struct Point*a2=(struct Point*)p2; int type=Cmp_PolarAngel(*a1, *a2, p0); if (type<0) return -1; else if (type==0) { if (a1->dis<a2->dis) return -1; else if (a1->dis==a2->dis) return 0; else return 1; } else return 1; } //求凸包 void Hull(int n) { int i, k; p0.x=p0.y=INF; for (i=0;i<n;i++) { scanf("%lf %lf",&pt[i].x, &pt[i].y); if (pt[i].y < p0.y) { p0.y=pt[i].y; p0.x=pt[i].x; k=i; } else if (pt[i].y==p0.y) { if (pt[i].x<p0.x) { p0.x=pt[i].x; k=i; } } } pt[k]= 4000 pt[0]; pt[0]=p0; for (i=1;i<n;i++) pt[i].dis=Dis(pt[i].x,pt[i].y, p0.x,p0.y); qsort(pt+1, n-1, sizeof(struct Point), Cmp); //去掉极角相同的点 tot=1; for (i=2;i<n;i++) if (Cmp_PolarAngel(pt[i], pt[i-1], p0)) pt[tot++]=pt[i-1]; pt[tot++]=pt[n-1]; //求凸包 top=1; stack[0]=pt[0]; stack[1]=pt[1]; for (i=2;i<tot;i++) { while (top>=1 && Is_LeftTurn(pt[i], stack[top], stack[top-1])==false) top--; stack[++top]=pt[i]; } } //计算叉积 double CrossProduct(struct Point p1, struct Point p2, struct Point p3) { return (p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y); } //卡壳旋转,求出凸多边形所有对踵点 double hl(double a,double b,double c) { double p=(a+b+c)/2.0; return sqrt(p*(p-a)*(p-b)*(p-c)); } double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void Rotate(struct Point*ch, int n) { int i, p=1; double t1, t2, ans=INF, dif; ch =ch[0]; for (i=0;i<n;i++) { //如果下一个点与当前边构成的三角形的面积更大,则说明此时不构成对踵点 while (fabs(CrossProduct(ch[i],ch[i+1],ch[p+1])) > fabs(CrossProduct(ch[i],ch[i+1],ch[p]))) p=(p+1)%n; dif=fabs(CrossProduct(ch[i],ch[i+1],ch[p+1])) - fabs(CrossProduct(ch[i],ch[i+1],ch[p])); //如果当前点和下一个点分别构成的三角形面积相等,则说明两条边即为平行线,对角线两端都可能是对踵点 t1=hl(dist(ch[i],ch[i+1]),dist(ch[i+1],ch[p]),dist(ch[p],ch[i]))*2.0/dist(ch[i],ch[i+1]); //printf(">>%lf\n",dist(ch[i],ch[i+1])); if (t1<ans)ans=t1; } printf("%.15lf\n",ans); } int main (void) { int n; scanf("%d%*d",&n); Hull(n); Rotate(stack, top+1); return 0; }
相关文章推荐
- codeforces Gym 100338E Numbers (贪心,实现)
- Codeforces Gym 100733H Designation in the Mafia flyod
- CodeForcesGym 100548G The Problem to Slow Down You
- Codeforces Gym 101138C Stickmen 暴力搜索+组合数
- codeforces gym 100645A
- Codeforces Gym 101201G Maximum Islands (dfs求联通块+最大独立集)
- Codeforces Gym 100002 B Bricks 枚举角度
- Codeforces Gym 100341I Hungry Queen 2 Set水题
- Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP
- Codeforces Gym 100342F Move to Front 平衡树
- codeforces Gym 100187 A. Potion of Immortality
- Codeforces Gym 101505(2016-2017 CTU Open Contest) D---群论、模拟
- Codeforces Gym 100548F Color (组合数+容斥)
- CodeForces Gym 100989L Plus or Minus (A) DFS
- Codeforces Gym 101505C : Cable Connection (计算几何)
- Codeforces GYM 100548 F - Color 2014-2015 ACM-ICPC, Asia Xian Regional Contest
- [Trie树建图 2-SAT] Codeforces Gym 101190 NEERC 16 B. Binary Code
- Codeforces Gym 101190 (NEERC 2016) H. Hard Refactoring (模拟 + 树状数组)
- Codeforces Gym 101164 F. Letter
- 【Codeforces Gym 100187F 】+ 贪心